debugger: re-enable basic support for reverse execution.

Needs polishing.
This commit is contained in:
hjk
2010-03-11 11:07:16 +01:00
parent 43215c8361
commit 60995cf0ab
6 changed files with 71 additions and 62 deletions

View File

@@ -313,7 +313,7 @@ void SavedAction::connectWidget(QWidget *widget, ApplyMode applyMode)
this, SLOT(pathChooserEditingFinished())); this, SLOT(pathChooserEditingFinished()));
connect(pathChooser, SIGNAL(browsingFinished()), connect(pathChooser, SIGNAL(browsingFinished()),
this, SLOT(pathChooserEditingFinished())); this, SLOT(pathChooserEditingFinished()));
} else if (QGroupBox *groupBox= qobject_cast<QGroupBox *>(widget)) { } else if (QGroupBox *groupBox = qobject_cast<QGroupBox *>(widget)) {
if (!groupBox->isCheckable()) if (!groupBox->isCheckable())
qDebug() << "connectWidget to non-checkable group box" << widget << toString(); qDebug() << "connectWidget to non-checkable group box" << widget << toString();
groupBox->setChecked(m_value.toBool()); groupBox->setChecked(m_value.toBool());
@@ -343,7 +343,7 @@ void SavedAction::apply(QSettings *s)
setValue(spinBox->value()); setValue(spinBox->value());
else if (PathChooser *pathChooser = qobject_cast<PathChooser *>(m_widget)) else if (PathChooser *pathChooser = qobject_cast<PathChooser *>(m_widget))
setValue(pathChooser->path()); setValue(pathChooser->path());
else if (const QGroupBox *groupBox= qobject_cast<QGroupBox *>(m_widget)) else if (const QGroupBox *groupBox = qobject_cast<QGroupBox *>(m_widget))
setValue(groupBox->isChecked()); setValue(groupBox->isChecked());
if (s) if (s)
writeSettings(s); writeSettings(s);

View File

@@ -513,6 +513,7 @@ void DebuggerManager::init()
d->m_actions.reverseDirectionAction = new QAction(tr("Reverse Direction"), this); d->m_actions.reverseDirectionAction = new QAction(tr("Reverse Direction"), this);
d->m_actions.reverseDirectionAction->setCheckable(true); d->m_actions.reverseDirectionAction->setCheckable(true);
d->m_actions.reverseDirectionAction->setChecked(false); d->m_actions.reverseDirectionAction->setChecked(false);
d->m_actions.reverseDirectionAction->setIcon(QIcon(":/debugger/images/location_16.png"));
connect(d->m_actions.continueAction, SIGNAL(triggered()), connect(d->m_actions.continueAction, SIGNAL(triggered()),
this, SLOT(executeContinue())); this, SLOT(executeContinue()));

View File

@@ -223,7 +223,8 @@ DebugMode::~DebugMode()
// //
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
class DebuggerListener : public Core::ICoreListener { class DebuggerListener : public Core::ICoreListener
{
Q_OBJECT Q_OBJECT
public: public:
explicit DebuggerListener(QObject *parent = 0); explicit DebuggerListener(QObject *parent = 0);
@@ -377,10 +378,6 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent)
m_group.insert(theDebuggerAction(BreakOnThrow), 0); m_group.insert(theDebuggerAction(BreakOnThrow), 0);
m_group.insert(theDebuggerAction(BreakOnCatch), 0); m_group.insert(theDebuggerAction(BreakOnCatch), 0);
#ifdef USE_REVERSE_DEBUGGING
m_ui.checkBoxEnableReverseDebugging->hide();
#endif
if (m_searchKeywords.isEmpty()) { if (m_searchKeywords.isEmpty()) {
QTextStream(&m_searchKeywords) << ' ' << m_ui.checkBoxListSourceFiles->text() QTextStream(&m_searchKeywords) << ' ' << m_ui.checkBoxListSourceFiles->text()
<< ' ' << m_ui.checkBoxUseMessageBoxForSignals->text() << ' ' << m_ui.checkBoxUseMessageBoxForSignals->text()
@@ -706,7 +703,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
const QList<Core::IOptionsPage *> engineOptionPages = const QList<Core::IOptionsPage *> engineOptionPages =
manager->initializeEngines(m_cmdLineEnabledEngines); manager->initializeEngines(m_cmdLineEnabledEngines);
// register factory of DebuggerRunControl // Register factory of DebuggerRunControl.
m_debuggerRunControlFactory = new DebuggerRunControlFactory(manager); m_debuggerRunControlFactory = new DebuggerRunControlFactory(manager);
addAutoReleasedObject(m_debuggerRunControlFactory); addAutoReleasedObject(m_debuggerRunControlFactory);
@@ -716,10 +713,9 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
context.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE)); context.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE));
m_debugMode->setContext(context); m_debugMode->setContext(context);
//Core::ActionContainer *mcppcontext = m_reverseToolButton = 0;
// am->actionContainer(CppEditor::Constants::M_CONTEXT);
// External apps // Handling of external applications.
m_startExternalAction = new QAction(this); m_startExternalAction = new QAction(this);
m_startExternalAction->setText(tr("Start and Debug External Application...")); m_startExternalAction->setText(tr("Start and Debug External Application..."));
connect(m_startExternalAction, SIGNAL(triggered()), connect(m_startExternalAction, SIGNAL(triggered()),
@@ -744,13 +740,9 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
connect(m_detachAction, SIGNAL(triggered()), connect(m_detachAction, SIGNAL(triggered()),
manager, SLOT(detachDebugger())); manager, SLOT(detachDebugger()));
// Core::ActionContainer *mdebug =
// am->actionContainer(ProjectExplorer::Constants::M_DEBUG);
Core::Command *cmd = 0; Core::Command *cmd = 0;
const DebuggerManagerActions actions = manager->debuggerManagerActions(); const DebuggerManagerActions actions = manager->debuggerManagerActions();
Core::ActionContainer *mstart = Core::ActionContainer *mstart =
am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING); am->actionContainer(ProjectExplorer::Constants::M_DEBUG_STARTDEBUGGING);
@@ -831,12 +823,10 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
Constants::RETURN_FROM_FUNCTION, debuggercontext); Constants::RETURN_FROM_FUNCTION, debuggercontext);
m_uiSwitcher->addMenuAction(cmd); m_uiSwitcher->addMenuAction(cmd);
#ifdef USE_REVERSE_DEBUGGING
cmd = am->registerAction(actions.reverseDirectionAction, cmd = am->registerAction(actions.reverseDirectionAction,
Constants::REVERSE, debuggercontext); Constants::REVERSE, debuggercontext);
cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY)); cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY));
m_uiSwitcher->addMenuAction(cmd); m_uiSwitcher->addMenuAction(cmd);
#endif
sep = new QAction(this); sep = new QAction(this);
sep->setSeparator(true); sep->setSeparator(true);
@@ -944,16 +934,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
handleStateChanged(DebuggerNotReady); handleStateChanged(DebuggerNotReady);
m_uiSwitcher->setToolbar(LANG_CPP, createToolbar()); // Toolbar
connect(m_uiSwitcher, SIGNAL(dockArranged(QString)), manager,
SLOT(setSimpleDockWidgetArrangement(QString)));
return true;
}
QWidget *DebuggerPlugin::createToolbar() const
{
Core::ActionManager *am = ICore::instance()->actionManager();
QWidget *toolbarContainer = new QWidget; QWidget *toolbarContainer = new QWidget;
QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer); QHBoxLayout *hbox = new QHBoxLayout(toolbarContainer);
@@ -965,10 +946,12 @@ QWidget *DebuggerPlugin::createToolbar() const
hbox->addWidget(toolButton(am->command(Constants::STEP)->action())); hbox->addWidget(toolButton(am->command(Constants::STEP)->action()));
hbox->addWidget(toolButton(am->command(Constants::STEPOUT)->action())); hbox->addWidget(toolButton(am->command(Constants::STEPOUT)->action()));
hbox->addWidget(toolButton(am->command(Constants::OPERATE_BY_INSTRUCTION)->action())); hbox->addWidget(toolButton(am->command(Constants::OPERATE_BY_INSTRUCTION)->action()));
#ifdef USE_REVERSE_DEBUGGING
hbox->addWidget(new Utils::StyledSeparator); //hbox->addWidget(new Utils::StyledSeparator);
hbox->addWidget(toolButton(am->command(Constants::REVERSE)->action())); m_reverseToolButton = toolButton(am->command(Constants::REVERSE)->action());
#endif hbox->addWidget(m_reverseToolButton);
//m_reverseToolButton->hide();
hbox->addWidget(new Utils::StyledSeparator); hbox->addWidget(new Utils::StyledSeparator);
hbox->addWidget(new QLabel(tr("Threads:"))); hbox->addWidget(new QLabel(tr("Threads:")));
@@ -980,7 +963,15 @@ QWidget *DebuggerPlugin::createToolbar() const
hbox->addWidget(threadBox); hbox->addWidget(threadBox);
hbox->addWidget(m_manager->statusLabel(), 10); hbox->addWidget(m_manager->statusLabel(), 10);
return toolbarContainer;
m_uiSwitcher->setToolbar(LANG_CPP, toolbarContainer);
connect(m_uiSwitcher, SIGNAL(dockArranged(QString)), manager,
SLOT(setSimpleDockWidgetArrangement(QString)));
connect(theDebuggerAction(EnableReverseDebugging), SIGNAL(valueChanged(QVariant)),
this, SLOT(enableReverseDebuggingTriggered(QVariant)));
return true;
} }
void DebuggerPlugin::extensionsInitialized() void DebuggerPlugin::extensionsInitialized()
@@ -1377,6 +1368,14 @@ void DebuggerPlugin::startRemoteApplication()
->startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE); ->startRunControl(runControl, ProjectExplorer::Constants::DEBUGMODE);
} }
void DebuggerPlugin::enableReverseDebuggingTriggered(const QVariant &value)
{
QTC_ASSERT(m_reverseToolButton, return);
m_reverseToolButton->setVisible(value.toBool());
if (!value.toBool())
m_manager->debuggerManagerActions().reverseDirectionAction->setChecked(false);
}
#include "debuggerplugin.moc" #include "debuggerplugin.moc"
Q_EXPORT_PLUGIN(DebuggerPlugin) Q_EXPORT_PLUGIN(DebuggerPlugin)

View File

@@ -37,10 +37,11 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction; class QAction;
class QComboBox;
class QCursor; class QCursor;
class QMenu; class QMenu;
class QPoint; class QPoint;
class QComboBox; class QToolButton;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace Core { namespace Core {
@@ -119,17 +120,19 @@ private slots:
void attachCore(); void attachCore();
void attachCmdLine(); void attachCmdLine();
void enableReverseDebuggingTriggered(const QVariant &value);
private: private:
void readSettings(); void readSettings();
void writeSettings() const; void writeSettings() const;
void attachExternalApplication(qint64 pid, const QString &crashParameter = QString()); void attachExternalApplication(qint64 pid, const QString &crashParameter = QString());
void attachCore(const QString &core, const QString &exeFileName); void attachCore(const QString &core, const QString &exeFileName);
QWidget *createToolbar() const;
friend class Debugger::DebuggerManager; friend class Debugger::DebuggerManager;
friend class GdbOptionPage; friend class GdbOptionPage;
friend class DebuggingHelperOptionPage; friend class DebuggingHelperOptionPage;
friend class Debugger::Internal::DebugMode; // FIXME: Just a hack now so that it can access the views // FIXME: Just a hack now so that it can access the views.
friend class Debugger::Internal::DebugMode;
DebuggerUISwitcher *m_uiSwitcher; DebuggerUISwitcher *m_uiSwitcher;
DebuggerManager *m_manager; DebuggerManager *m_manager;
@@ -148,6 +151,7 @@ private:
QAction *m_attachCoreAction; QAction *m_attachCoreAction;
QAction *m_detachAction; QAction *m_detachAction;
QComboBox *m_langBox; QComboBox *m_langBox;
QToolButton *m_reverseToolButton;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -217,7 +217,7 @@ QMainWindow *GdbEngine::mainWindow() const
GdbEngine::~GdbEngine() GdbEngine::~GdbEngine()
{ {
// prevent sending error messages afterwards // Prevent sending error messages afterwards.
disconnect(&m_gdbProc, 0, this, 0); disconnect(&m_gdbProc, 0, this, 0);
delete m_gdbAdapter; delete m_gdbAdapter;
m_gdbAdapter = 0; m_gdbAdapter = 0;
@@ -229,13 +229,10 @@ void GdbEngine::connectAdapter()
this, SLOT(handleAdapterStarted())); this, SLOT(handleAdapterStarted()));
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)), connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
this, SLOT(handleAdapterStartFailed(QString,QString))); this, SLOT(handleAdapterStartFailed(QString,QString)));
connect(m_gdbAdapter, SIGNAL(inferiorPrepared()), connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
this, SLOT(handleInferiorPrepared())); this, SLOT(handleInferiorPrepared()));
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)), connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
this, SLOT(handleInferiorStartFailed(QString))); this, SLOT(handleInferiorStartFailed(QString)));
connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)), connect(m_gdbAdapter, SIGNAL(adapterCrashed(QString)),
this, SLOT(handleAdapterCrashed(QString))); this, SLOT(handleAdapterCrashed(QString)));
} }
@@ -1257,7 +1254,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
// return; // return;
// } // }
// jump over well-known frames // Jump over well-known frames.
static int stepCounter = 0; static int stepCounter = 0;
if (theDebuggerBoolSetting(SkipKnownFrames)) { if (theDebuggerBoolSetting(SkipKnownFrames)) {
if (reason == "end-stepping-range" || reason == "function-finished") { if (reason == "end-stepping-range" || reason == "function-finished") {
@@ -1537,7 +1534,7 @@ void GdbEngine::handleExecuteContinue(const GdbResponse &response)
//executeStepOut(); //executeStepOut();
} else { } else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"), showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
shutdown(); shutdown();
} }
} }
@@ -1781,7 +1778,7 @@ void GdbEngine::executeStep()
if (m_gdbAdapter->isTrkAdapter() && stackHandler->stackSize() > 0) if (m_gdbAdapter->isTrkAdapter() && stackHandler->stackSize() > 0)
postCommand("sal step," + stackHandler->topAddress().toLatin1()); postCommand("sal step," + stackHandler->topAddress().toLatin1());
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-step", RunRequest, CB(handleExecuteStep)); postCommand("reverse-step", RunRequest, CB(handleExecuteStep));
else else
postCommand("-exec-step", RunRequest, CB(handleExecuteStep)); postCommand("-exec-step", RunRequest, CB(handleExecuteStep));
} }
@@ -1789,7 +1786,7 @@ void GdbEngine::executeStep()
void GdbEngine::handleExecuteStep(const GdbResponse &response) void GdbEngine::handleExecuteStep(const GdbResponse &response)
{ {
if (response.resultClass == GdbResultRunning) { if (response.resultClass == GdbResultRunning) {
// The "running" state is picked up in handleResponse() // The "running" state is picked up in handleResponse().
QTC_ASSERT(state() == InferiorRunning, /**/); QTC_ASSERT(state() == InferiorRunning, /**/);
} else { } else {
if (state() == InferiorRunningRequested_Kill) { if (state() == InferiorRunningRequested_Kill) {
@@ -1806,7 +1803,8 @@ void GdbEngine::handleExecuteStep(const GdbResponse &response)
executeStepI(); // Fall back to instruction-wise stepping. executeStepI(); // Fall back to instruction-wise stepping.
} else { } else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"), showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); tr("Cannot continue debugged process:\n")
+ QString::fromLocal8Bit(msg));
shutdown(); shutdown();
} }
} }
@@ -1819,7 +1817,7 @@ void GdbEngine::executeStepI()
setState(InferiorRunningRequested); setState(InferiorRunningRequested);
showStatusMessage(tr("Step by instruction requested..."), 5000); showStatusMessage(tr("Step by instruction requested..."), 5000);
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-stepi", RunRequest, CB(handleExecuteContinue)); postCommand("reverse-stepi", RunRequest, CB(handleExecuteContinue));
else else
postCommand("-exec-step-instruction", RunRequest, CB(handleExecuteContinue)); postCommand("-exec-step-instruction", RunRequest, CB(handleExecuteContinue));
} }
@@ -1843,7 +1841,7 @@ void GdbEngine::executeNext()
if (m_gdbAdapter->isTrkAdapter() && stackHandler->stackSize() > 0) if (m_gdbAdapter->isTrkAdapter() && stackHandler->stackSize() > 0)
postCommand("sal next," + stackHandler->topAddress().toLatin1()); postCommand("sal next," + stackHandler->topAddress().toLatin1());
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-next", RunRequest, CB(handleExecuteNext)); postCommand("reverse-next", RunRequest, CB(handleExecuteNext));
else else
postCommand("-exec-next", RunRequest, CB(handleExecuteNext)); postCommand("-exec-next", RunRequest, CB(handleExecuteNext));
} }
@@ -1868,7 +1866,7 @@ void GdbEngine::handleExecuteNext(const GdbResponse &response)
executeNextI(); // Fall back to instruction-wise stepping. executeNextI(); // Fall back to instruction-wise stepping.
} else { } else {
showMessageBox(QMessageBox::Critical, tr("Execution Error"), showMessageBox(QMessageBox::Critical, tr("Execution Error"),
tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg));
shutdown(); shutdown();
} }
} }
@@ -1881,7 +1879,7 @@ void GdbEngine::executeNextI()
setState(InferiorRunningRequested); setState(InferiorRunningRequested);
showStatusMessage(tr("Step next instruction requested..."), 5000); showStatusMessage(tr("Step next instruction requested..."), 5000);
if (manager()->isReverseDebugging()) if (manager()->isReverseDebugging())
postCommand("-reverse-nexti", RunRequest, CB(handleExecuteContinue)); postCommand("reverse-nexti", RunRequest, CB(handleExecuteContinue));
else else
postCommand("-exec-next-instruction", RunRequest, CB(handleExecuteContinue)); postCommand("-exec-next-instruction", RunRequest, CB(handleExecuteContinue));
} }
@@ -3854,26 +3852,29 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:" // "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
GdbMi output = response.data.findChild("consolestreamoutput"); GdbMi output = response.data.findChild("consolestreamoutput");
QStringList res; QStringList res;
QString out = QString::fromLatin1(output.data()).trimmed(); foreach (QByteArray line, output.data().split('\n')) {
foreach (const QString &line, out.split(_c('\n'))) { line = line.trimmed();
if (line.startsWith(_("Current language:"))) if (line.startsWith("=> "))
line = line.mid(3);
if (line.startsWith("Current language:"))
continue; continue;
if (line.startsWith(_("The current source"))) if (line.startsWith("The current source"))
continue; continue;
if (line.startsWith(_("0x"))) { if (line.startsWith("0x")) {
int pos1 = line.indexOf(_c('<')); int pos1 = line.indexOf('<');
int pos2 = line.indexOf(_c('+'), pos1); int pos2 = line.indexOf('+', pos1);
int pos3 = line.indexOf(_c('>'), pos2); int pos3 = line.indexOf('>', pos2);
if (pos3 >= 0) { if (pos3 >= 0) {
QString ba = _(" <+") + line.mid(pos2 + 1, pos3 - pos2 - 1); QByteArray ba = " <+" + line.mid(pos2 + 1, pos3 - pos2 - 1);
res.append(line.left(pos1 - 1) + ba.rightJustified(4) ba = line.left(pos1 - 1) + ba.rightJustified(4)
+ _(">: ") + line.mid(pos3 + 2)); + ">: " + line.mid(pos3 + 2);
res.append(_(ba));
} else { } else {
res.append(line); res.append(_(line));
} }
continue; continue;
} }
res.append(someSpace + line); res.append(someSpace + _(line));
} }
// Drop "End of assembler dump." line. // Drop "End of assembler dump." line.
res.takeLast(); res.takeLast();

View File

@@ -32,6 +32,7 @@
#include "gdbengine.h" #include "gdbengine.h"
#include "procinterrupt.h" #include "procinterrupt.h"
#include "debuggerstringutils.h" #include "debuggerstringutils.h"
#include "debuggeractions.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -163,9 +164,12 @@ void PlainGdbAdapter::handleExecRun(const GdbResponse &response)
QTC_ASSERT(state() == InferiorRunning, qDebug() << state()); QTC_ASSERT(state() == InferiorRunning, qDebug() << state());
debugMessage(_("INFERIOR STARTED")); debugMessage(_("INFERIOR STARTED"));
showStatusMessage(msgInferiorStarted()); showStatusMessage(msgInferiorStarted());
// FIXME: That's the wrong place for it.
if (theDebuggerBoolSetting(EnableReverseDebugging))
m_engine->postCommand("target record");
} else { } else {
QTC_ASSERT(state() == InferiorRunningRequested, qDebug() << state()); QTC_ASSERT(state() == InferiorRunningRequested, qDebug() << state());
const QString &msg = QString::fromLocal8Bit(response.data.findChild("msg").data()); QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
//QTC_ASSERT(status() == InferiorRunning, /**/); //QTC_ASSERT(status() == InferiorRunning, /**/);
//interruptInferior(); //interruptInferior();
emit inferiorStartFailed(msg); emit inferiorStartFailed(msg);