Commit 9757e221 authored by hjk's avatar hjk

debugger: introduce the concept of a 'Location', used by gotoLocation

parent 39c145bf
......@@ -894,15 +894,12 @@ void BreakHandler::gotoLocation(BreakpointId id) const
QTC_ASSERT(it != m_storage.end(), return);
DebuggerEngine *engine = debuggerCore()->currentEngine();
if (it->data.type == BreakpointByAddress) {
StackFrame frame;
frame.address = it->data.address;
if (engine)
engine->gotoLocation(frame, false);
engine->gotoLocation(it->data.address);
} else {
const QString fileName = it->markerFileName();
const int lineNumber = it->markerLineNumber();
if (engine)
engine->gotoLocation(fileName, lineNumber, false);
engine->gotoLocation(
Location(it->markerFileName(), it->markerLineNumber()));
}
}
......
......@@ -1049,7 +1049,7 @@ void CdbEngine::executeJumpToLine(const QString &fileName, int lineNumber)
frame.usable = true;
frame.file = fileName;
frame.line = lineNumber;
gotoLocation(frame, true);
gotoLocation(frame);
success = true;
} while (false);
if (!success)
......@@ -1166,7 +1166,7 @@ void CdbEngine::activateFrame(int frameIndex)
break;
}
gotoLocation(frame, true);
gotoLocation(frame);
if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) {
watchHandler()->beginCycle();
......
......@@ -831,7 +831,7 @@ void CdbEngine::handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &cm
// PC-register depending on 64/32bit.
str << "r " << (m_options->is64bit ? "rip" : "eip") << "=0x" << answer;
postCommand(registerCmd, 0);
gotoLocation(cookie.fileName, cookie.lineNumber, true);
gotoLocation(Location(cookie.fileName, cookie.lineNumber));
}
void CdbEngine::assignValueInDebugger(const Debugger::Internal::WatchData *w, const QString &expr, const QVariant &value)
......@@ -979,13 +979,13 @@ void CdbEngine::activateFrame(int index)
watchHandler()->endCycle();
QAction *assemblerAction = theAssemblerAction();
if (assemblerAction->isChecked()) {
gotoLocation(frame, true);
gotoLocation(frame);
} else {
assemblerAction->trigger(); // Seems to trigger update
}
return;
}
gotoLocation(frame, true);
gotoLocation(frame);
// Watchers: Initial expand, get uninitialized and query
QByteArray arguments;
ByteArrayInputStream str(arguments);
......
......@@ -512,14 +512,21 @@ void DebuggerEngine::resetLocation()
d->removeLocationMark();
}
void DebuggerEngine::gotoLocation(const QString &file, int line, bool setMarker)
void DebuggerEngine::gotoLocation(const Location &loc)
{
if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) {
d->m_disassemblerAgent.setTryMixed(true);
d->m_disassemblerAgent.setLocation(loc);
return;
}
// CDB might hit on breakpoints while shutting down.
//if (m_shuttingDown)
// return;
d->doRemoveLocationMark();
const QString file = loc.fileName();
const int line = loc.lineNumber();
EditorManager *editorManager = EditorManager::instance();
QList<IEditor *> editors = editorManager->editorsForFileName(file);
if (editors.isEmpty()) {
......@@ -531,23 +538,15 @@ void DebuggerEngine::gotoLocation(const QString &file, int line, bool setMarker)
if (texteditor)
texteditor->gotoLine(line, 0);
if (setMarker)
if (loc.needsMarker())
d->m_locationMark.reset(new LocationMark(file, line));
// FIXME: Breaks with split views.
if (!d->m_memoryAgent.hasVisibleEditor())
if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise())
editorManager->activateEditor(editors.back());
//qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor();
}
void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{
if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable())
d->m_disassemblerAgent.setFrame(frame, true, setMarker);
else
gotoLocation(frame.file, frame.line, setMarker);
}
// Called from RunControl.
void DebuggerEngine::handleStartFailed()
{
......@@ -1469,10 +1468,11 @@ void DebuggerEngine::updateMemoryViews()
d->m_memoryAgent.updateContents();
}
void DebuggerEngine::openDisassemblerView(const StackFrame &frame)
void DebuggerEngine::openDisassemblerView(const Location &location)
{
DisassemblerAgent *agent = new DisassemblerAgent(this);
agent->setFrame(frame, true, false);
agent->setTryMixed(true);
agent->setLocation(location);
}
void DebuggerEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
......
......@@ -34,6 +34,7 @@
#include "debuggerconstants.h"
#include "moduleshandler.h" // For 'Symbols'
#include "breakpoint.h" // For 'BreakpointId'
#include "stackframe.h"
#include <coreplugin/ssh/sshconnection.h>
......@@ -141,6 +142,42 @@ struct WatchUpdateFlags
bool tryIncremental;
};
class Location
{
public:
Location() { init(); }
Location(quint64 address) { init(); m_address = address; }
Location(const QString &file) { init(); m_fileName = file; }
Location(const QString &file, int line, bool marker = true)
{ init(); m_lineNumber = line; m_fileName = file; m_needsMarker = marker; }
Location(const StackFrame &frame, bool marker = true) //: m_frame(frame)
{ init(); m_fileName = frame.file; m_lineNumber = frame.line;
m_needsMarker = marker; m_functionName = frame.function;
m_hasDebugInfo = frame.isUsable(); m_address = frame.address; }
QString fileName() const { return m_fileName; }
QString functionName() const { return m_functionName; }
int lineNumber() const { return m_lineNumber; }
void setNeedsRaise(bool on) { m_needsRaise = on; }
void setNeedsMarker(bool on) { m_needsMarker = on; }
void setFileName(const QString &fileName) { m_fileName = fileName; }
bool needsRaise() const { return m_needsRaise; }
bool needsMarker() const { return m_needsMarker; }
bool hasDebugInfo() const { return m_hasDebugInfo; }
quint64 address() const { return m_address; }
private:
void init() { m_needsMarker = false; m_needsRaise = true; m_lineNumber = -1;
m_address = 0; m_hasDebugInfo = true; }
bool m_needsMarker;
bool m_needsRaise;
bool m_hasDebugInfo;
int m_lineNumber;
QString m_fileName;
QString m_functionName;
quint64 m_address;
};
} // namespace Internal
......@@ -166,7 +203,7 @@ public:
virtual void fetchMemory(Internal::MemoryAgent *, QObject *,
quint64 addr, quint64 length);
virtual void updateMemoryViews();
virtual void openDisassemblerView(const Internal::StackFrame &frame);
virtual void openDisassemblerView(const Internal::Location &location);
virtual void fetchDisassembler(Internal::DisassemblerAgent *);
virtual void activateFrame(int index);
......@@ -280,9 +317,7 @@ public:
Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const;
void resetLocation();
virtual void gotoLocation(const QString &fileName, int lineNumber = -1,
bool setMarker = false);
virtual void gotoLocation(const Internal::StackFrame &frame, bool setMarker);
virtual void gotoLocation(const Internal::Location &location);
virtual void quitDebugger(); // called by DebuggerRunControl
virtual void updateViews();
......@@ -292,7 +327,7 @@ signals:
void stateChanged(const DebuggerState &state);
void updateViewsRequested();
/*
* For "external" clients of a debugger run control that need to do
* For "external" clients of a debugger run control that needs to do
* further setup before the debugger is started (e.g. Maemo).
* Afterwards, handleSetupDone() or handleSetupFailed() must be called
* to continue or abort debugging, respectively.
......
......@@ -1240,8 +1240,9 @@ public slots:
// Go to source only if we have the file.
if (currentEngine()->stackHandler()->currentIndex() >= 0) {
const StackFrame frame = currentEngine()->stackHandler()->currentFrame();
if (operateByInstructionTriggered || frame.isUsable())
currentEngine()->gotoLocation(frame, true);
if (operateByInstructionTriggered || frame.isUsable()) {
currentEngine()->gotoLocation(Location(frame, true));
}
}
}
......
......@@ -100,9 +100,8 @@ public:
public:
QPointer<TextEditor::ITextEditor> editor;
StackFrame frame;
Location location;
bool tryMixed;
bool setMarker;
QPointer<DebuggerEngine> engine;
TextEditor::ITextMark *locationMark;
QList<TextEditor::ITextMark *> breakpointMarks;
......@@ -114,7 +113,6 @@ public:
DisassemblerAgentPrivate::DisassemblerAgentPrivate()
: editor(0),
tryMixed(true),
setMarker(true),
locationMark(new LocationMark2),
mimeType(_("text/x-qtcreator-generic-asm"))
{
......@@ -162,36 +160,34 @@ void DisassemblerAgent::resetLocation()
d->editor->markableInterface()->removeMark(d->locationMark);
}
QString frameKey(const StackFrame &frame)
static QString frameKey(const Location &loc)
{
return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from);
return _("%1:%2:%3").arg(loc.functionName())
.arg(loc.fileName()).arg(loc.address());
}
const StackFrame &DisassemblerAgent::frame() const
const Location &DisassemblerAgent::location() const
{
return d->frame;
return d->location;
}
bool DisassemblerAgent::isMixed() const
{
return d->tryMixed
&& d->frame.line > 0
&& !d->frame.function.isEmpty()
&& d->frame.function != _("??");
&& d->location.lineNumber() > 0
&& !d->location.functionName().isEmpty()
&& d->location.functionName() != _("??");
}
void DisassemblerAgent::setFrame(const StackFrame &frame,
bool tryMixed, bool setMarker)
void DisassemblerAgent::setLocation(const Location &loc)
{
d->frame = frame;
d->tryMixed = tryMixed;
d->setMarker = setMarker;
d->location = loc;
if (isMixed()) {
QHash<QString, DisassemblerLines>::ConstIterator it =
d->cache.find(frameKey(frame));
d->cache.find(frameKey(loc));
if (it != d->cache.end()) {
QString msg = _("Use cache disassembler for '%1' in '%2'")
.arg(frame.function).arg(frame.file);
.arg(loc.functionName()).arg(loc.fileName());
d->engine->showMessage(msg);
setContents(*it);
updateBreakpointMarkers();
......@@ -280,8 +276,9 @@ void DisassemblerAgent::setContents(const DisassemblerLines &contents)
plainTextEdit->setPlainText(str);
plainTextEdit->setReadOnly(true);
d->cache.insert(frameKey(d->frame), contents);
d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
d->cache.insert(frameKey(d->location), contents);
d->editor->setDisplayName(_("Disassembler (%1)")
.arg(d->location.functionName()));
updateBreakpointMarkers();
updateLocationMarker();
......@@ -291,10 +288,10 @@ void DisassemblerAgent::updateLocationMarker()
{
QTC_ASSERT(d->editor, return);
const DisassemblerLines &contents = d->cache.value(frameKey(d->frame));
int lineNumber = contents.lineForAddress(d->frame.address);
const DisassemblerLines &contents = d->cache.value(frameKey(d->location));
int lineNumber = contents.lineForAddress(d->location.address());
if (d->setMarker) {
if (d->location.needsMarker()) {
d->editor->markableInterface()->removeMark(d->locationMark);
if (lineNumber)
d->editor->markableInterface()->addMark(d->locationMark, lineNumber);
......@@ -319,7 +316,7 @@ void DisassemblerAgent::updateBreakpointMarkers()
if (ids.isEmpty())
return;
const DisassemblerLines &contents = d->cache.value(frameKey(d->frame));
const DisassemblerLines &contents = d->cache.value(frameKey(d->location));
foreach (TextEditor::ITextMark *marker, d->breakpointMarks)
d->editor->markableInterface()->removeMark(marker);
......@@ -339,7 +336,7 @@ void DisassemblerAgent::updateBreakpointMarkers()
quint64 DisassemblerAgent::address() const
{
return d->frame.address;
return d->location.address();
}
// Return address of an assembly line "0x0dfd bla"
......@@ -348,5 +345,10 @@ quint64 DisassemblerAgent::addressFromDisassemblyLine(const QString &line)
return DisassemblerLine(line).address;
}
void DisassemblerAgent::setTryMixed(bool on)
{
d->tryMixed = on;
}
} // namespace Internal
} // namespace Debugger
......@@ -45,8 +45,7 @@ class DebuggerEngine;
namespace Internal {
class StackFrame;
class DisassemblerAgent;
class Location;
class DisassemblerAgentPrivate;
class DisassemblerAgent : public QObject
......@@ -58,8 +57,9 @@ public:
explicit DisassemblerAgent(DebuggerEngine *engine);
~DisassemblerAgent();
void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker);
const StackFrame &frame() const;
void setTryMixed(bool on);
void setLocation(const Location &location);
const Location &location() const;
void resetLocation();
void setContents(const DisassemblerLines &contents);
void updateLocationMarker();
......
......@@ -1058,7 +1058,7 @@ void GdbEngine::handleExecuteRunToLine(const GdbResponse &response)
//>~"testArray () at ../simple/app.cpp:241\n"
//>~"241\t s[1] = \"b\";\n"
//>122^done
gotoLocation(m_targetFrame, true);
gotoLocation(m_targetFrame);
showStatusMessage(tr("Target line hit. Stopped"));
notifyInferiorSpontaneousStop();
handleStop1(response);
......@@ -1173,7 +1173,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// Quickly set the location marker.
if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction)
&& QFileInfo(fullName).exists())
gotoLocation(fullName, lineNumber, true);
gotoLocation(Location(fullName, lineNumber));
if (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state())
......@@ -1955,11 +1955,11 @@ void GdbEngine::executeJumpToLine(const QString &fileName, int lineNumber)
// ~"run1 (argc=1, argv=0x7fffbf1f5538) at test1.cpp:242"
// ~"242\t x *= 2;"
// 23^done"
gotoLocation(frame, true);
gotoLocation(frame);
//setBreakpoint();
//postCommand("jump " + loc);
#else
gotoLocation(frame, true);
gotoLocation(frame);
setBreakpoint(fileName, lineNumber);
notifyInferiorRunRequested();
postCommand("jump " + loc, RunRequest);
......@@ -2969,7 +2969,7 @@ void GdbEngine::activateFrame(int frameIndex)
handler->setCurrentIndex(frameIndex);
postCommand("-stack-select-frame " + QByteArray::number(frameIndex),
Discardable, CB(handleStackSelectFrame));
gotoLocation(stackHandler()->currentFrame(), true);
gotoLocation(stackHandler()->currentFrame());
updateLocals();
reloadRegisters();
}
......
......@@ -236,7 +236,7 @@ void IPCEngineHost::selectThread(int index)
void IPCEngineHost::fetchDisassembler(DisassemblerAgent *v)
{
quint64 address = v->frame().address;
quint64 address = v->location().address();
m_frameToDisassemblerAgent.insert(address, v);
QByteArray p;
{
......@@ -426,7 +426,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload)
StackHandler *sh = stackHandler();
sh->setCurrentIndex(token);
if (!sh->currentFrame().isUsable() || QFileInfo(sh->currentFrame().file).exists())
gotoLocation(sh->currentFrame(), true);
gotoLocation(Location(sh->currentFrame(), true));
else if (!m_sourceAgents.contains(sh->currentFrame().file))
fetchFrameSource(token);
foreach(SourceAgent *agent, m_sourceAgents.values())
......
......@@ -318,7 +318,7 @@ void PdbEngine::activateFrame(int frameIndex)
//postCommand("-stack-select-frame " + QByteArray::number(frameIndex),
// CB(handleStackSelectFrame));
}
gotoLocation(handler->currentFrame(), true);
gotoLocation(handler->currentFrame());
}
void PdbEngine::selectThread(int index)
......@@ -683,7 +683,7 @@ void PdbEngine::handleResponse(const QByteArray &response0)
frame.file = _(fileName);
frame.line = lineNumber;
if (frame.line > 0 && QFileInfo(frame.file).exists()) {
gotoLocation(frame, true);
gotoLocation(frame);
notifyInferiorSpontaneousStop();
return;
}
......@@ -797,7 +797,7 @@ void PdbEngine::handleBacktrace(const PdbResponse &response)
if (currentIndex != -1) {
currentIndex = frameCount - currentIndex - 1;
stackHandler()->setCurrentIndex(currentIndex);
gotoLocation(stackFrames.at(currentIndex), true);
gotoLocation(stackFrames.at(currentIndex));
}
updateLocals();
......
......@@ -176,23 +176,12 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
QmlEngine::~QmlEngine()
{}
void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker)
void QmlEngine::gotoLocation(const Location &loc0)
{
QString processedFilename = fileName;
Location loc = loc0;
if (isShadowBuildProject())
processedFilename = fromShadowBuildFilename(fileName);
DebuggerEngine::gotoLocation(processedFilename, lineNumber, setMarker);
}
void QmlEngine::gotoLocation(const StackFrame &frame, bool setMarker)
{
StackFrame adjustedFrame = frame;
if (isShadowBuildProject())
adjustedFrame.file = fromShadowBuildFilename(frame.file);
DebuggerEngine::gotoLocation(adjustedFrame, setMarker);
loc.setFileName(fromShadowBuildFilename(loc0.fileName()));
DebuggerEngine::gotoLocation(loc);
}
void QmlEngine::setupInferior()
......@@ -469,7 +458,7 @@ void QmlEngine::activateFrame(int index)
<< index;
logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(index)));
sendMessage(reply);
gotoLocation(stackHandler()->frames().value(index), true);
gotoLocation(stackHandler()->frames().value(index));
}
void QmlEngine::selectThread(int index)
......@@ -703,7 +692,7 @@ void QmlEngine::messageReceived(const QByteArray &message)
for (int i = 0; i != stackFrames.size(); ++i)
stackFrames[i].level = i + 1;
gotoLocation(stackFrames.value(0), true);
gotoLocation(stackFrames.value(0));
stackHandler()->setFrames(stackFrames);
watchHandler()->beginCycle();
......
......@@ -51,9 +51,7 @@ public:
void handleRemoteSetupDone(int port);
void handleRemoteSetupFailed(const QString &message);
void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
void gotoLocation(const StackFrame &frame, bool setMarker);
void gotoLocation(const Location &location);
void pauseConnection();
public slots:
......
......@@ -642,11 +642,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction)
notifyInferiorSpontaneousStop();
SDEBUG("Stopped at " << lineNumber << fileName);
showStatusMessage(tr("Stopped at %1:%2.").arg(fileName).arg(lineNumber), 5000);
StackFrame frame;
frame.file = fileName;
frame.line = lineNumber;
gotoLocation(frame, true);
gotoLocation(Location(fileName, lineNumber));
updateLocals();
return true;
}
......
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