Commit b2598d00 authored by hjk's avatar hjk

debugger: initial work on remote debugging

parent 78e48223
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>561</width>
<height>866</height>
<width>310</width>
<height>224</height>
</rect>
</property>
<property name="windowTitle">
......@@ -22,58 +22,35 @@
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="pidLabel">
<widget class="QLabel" name="channelLabel">
<property name="text">
<string>Attach to Process ID:</string>
<string>Host and Port:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="pidLineEdit"/>
<widget class="QLineEdit" name="channelLineEdit">
<property name="text">
<string>localhost:5115</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<widget class="QLabel" name="architectureLabel">
<property name="text">
<string>Filter:</string>
<string>Architecture:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="filterWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="filterLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="filterClearToolButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QComboBox" name="architectureComboBox"/>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="procView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
......
......@@ -51,7 +51,7 @@
namespace Debugger {
namespace Internal {
namespace Internal {
bool operator<(const ProcData &p1, const ProcData &p2)
{
......@@ -59,7 +59,8 @@ bool operator<(const ProcData &p1, const ProcData &p2)
}
// A filterable process list model
class ProcessListFilterModel : public QSortFilterProxyModel {
class ProcessListFilterModel : public QSortFilterProxyModel
{
public:
explicit ProcessListFilterModel(QObject *parent);
QString processIdAt(const QModelIndex &index) const;
......@@ -69,9 +70,9 @@ private:
QStandardItemModel *m_model;
};
ProcessListFilterModel::ProcessListFilterModel(QObject *parent) :
QSortFilterProxyModel(parent),
m_model(new QStandardItemModel(this))
ProcessListFilterModel::ProcessListFilterModel(QObject *parent)
: QSortFilterProxyModel(parent),
m_model(new QStandardItemModel(this))
{
QStringList columns;
columns << AttachExternalDialog::tr("Process ID")
......@@ -116,6 +117,7 @@ void ProcessListFilterModel::populate(QList<ProcData> processes, const QString &
}
}
///////////////////////////////////////////////////////////////////////
//
// AttachCoreDialog
......@@ -164,9 +166,10 @@ void AttachCoreDialog::setCoreFile(const QString &fileName)
m_ui->coreFileName->setPath(fileName);
}
///////////////////////////////////////////////////////////////////////
//
// process model helpers
// Process model helpers
//
///////////////////////////////////////////////////////////////////////
......@@ -224,11 +227,11 @@ static QList<ProcData> processList()
//
///////////////////////////////////////////////////////////////////////
AttachExternalDialog::AttachExternalDialog(QWidget *parent) :
QDialog(parent),
m_selfPid(QString::number(QCoreApplication::applicationPid())),
m_ui(new Ui::AttachExternalDialog),
m_model(new ProcessListFilterModel(this))
AttachExternalDialog::AttachExternalDialog(QWidget *parent)
: QDialog(parent),
m_selfPid(QString::number(QCoreApplication::applicationPid())),
m_ui(new Ui::AttachExternalDialog),
m_model(new ProcessListFilterModel(this))
{
m_ui->setupUi(this);
okButton()->setDefault(true);
......@@ -292,48 +295,26 @@ int AttachExternalDialog::attachPID() const
void AttachExternalDialog::pidChanged(const QString &pid)
{
okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid);
bool enabled = !pid.isEmpty() && pid != QLatin1String("0") && pid != m_selfPid;;
okButton()->setEnabled(enabled);
}
///////////////////////////////////////////////////////////////////////
//
// AttachRemoteDialog
//
///////////////////////////////////////////////////////////////////////
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) :
QDialog(parent),
m_ui(new Ui::AttachRemoteDialog),
m_model(new ProcessListFilterModel(this))
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent)
: QDialog(parent),
m_ui(new Ui::AttachRemoteDialog)
{
m_ui->setupUi(this);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
m_defaultPID = pid;
m_ui->procView->setModel(m_model);
m_ui->procView->setSortingEnabled(true);
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
// Do not use activated, will be single click in Oxygen
connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
this, SLOT(procSelected(QModelIndex)));
QPushButton *refreshButton = new QPushButton(tr("Refresh"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(m_ui->pidLineEdit, SIGNAL(textChanged(QString)),
this, SLOT(pidChanged(QString)));
connect(m_ui->filterClearToolButton, SIGNAL(clicked()),
m_ui->filterLineEdit, SLOT(clear()));
connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)),
m_model, SLOT(setFilterFixedString(QString)));
m_ui->pidLineEdit->setText(m_defaultPID);
rebuildProcessList();
}
AttachRemoteDialog::~AttachRemoteDialog()
......@@ -341,37 +322,36 @@ AttachRemoteDialog::~AttachRemoteDialog()
delete m_ui;
}
QPushButton *AttachRemoteDialog::okButton() const
void AttachRemoteDialog::setRemoteChannel(const QString &channel)
{
return m_ui->buttonBox->button(QDialogButtonBox::Ok);
m_ui->channelLineEdit->setText(channel);
}
void AttachRemoteDialog::rebuildProcessList()
QString AttachRemoteDialog::remoteChannel() const
{
m_model->populate(processList());
m_ui->procView->expandAll();
m_ui->procView->resizeColumnToContents(0);
m_ui->procView->resizeColumnToContents(1);
return m_ui->channelLineEdit->text();
}
void AttachRemoteDialog::procSelected(const QModelIndex &index0)
{
const QString proccessId = m_model->processIdAt(index0);
if (!proccessId.isEmpty()) {
m_ui->pidLineEdit->setText(proccessId);
if (okButton()->isEnabled())
okButton()->animateClick();
void AttachRemoteDialog::setRemoteArchitectures(const QStringList &list)
{
m_ui->architectureComboBox->clear();
if (!list.isEmpty()) {
m_ui->architectureComboBox->insertItems(0, list);
m_ui->architectureComboBox->setCurrentIndex(0);
}
}
int AttachRemoteDialog::attachPID() const
void AttachRemoteDialog::setRemoteArchitecture(const QString &arch)
{
return m_ui->pidLineEdit->text().toInt();
int index = m_ui->architectureComboBox->findText(arch);
if (index != -1)
m_ui->architectureComboBox->setCurrentIndex(index);
}
void AttachRemoteDialog::pidChanged(const QString &pid)
QString AttachRemoteDialog::remoteArchitecture() const
{
okButton()->setEnabled(!pid.isEmpty() && pid != QLatin1String("0"));
int index = m_ui->architectureComboBox->currentIndex();
return m_ui->architectureComboBox->itemText(index);
}
......@@ -426,5 +406,5 @@ QString StartExternalDialog::executableArguments() const
return m_ui->argsEdit->text();
}
}
}
} // namespace Internal
} // namespace Debugger
......@@ -101,30 +101,24 @@ private:
ProcessListFilterModel *m_model;
};
class AttachRemoteDialog : public QDialog
{
Q_OBJECT
public:
explicit AttachRemoteDialog(QWidget *parent, const QString &pid);
explicit AttachRemoteDialog(QWidget *parent);
~AttachRemoteDialog();
int attachPID() const;
private slots:
void rebuildProcessList();
void procSelected(const QModelIndex &);
void pidChanged(const QString &);
void setRemoteChannel(const QString &host);
void setRemoteArchitecture(const QString &arch);
void setRemoteArchitectures(const QStringList &arches);
QString remoteChannel() const;
QString remoteArchitecture() const;
private:
inline QPushButton *okButton() const;
Ui::AttachRemoteDialog *m_ui;
QString m_defaultPID;
ProcessListFilterModel *m_model;
};
class StartExternalDialog : public QDialog
{
Q_OBJECT
......
......@@ -89,6 +89,7 @@ using namespace Debugger::Constants;
static const QString tooltipIName = "tooltip";
#define _(s) QString::fromLatin1(s)
static const char *stateName(int s)
{
......@@ -304,6 +305,11 @@ void DebuggerManager::init()
m_attachCoreAction->setText(tr("Attach to Core..."));
connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
m_attachRemoteAction = new QAction(this);
m_attachRemoteAction->setText(tr("Attach to Running Remote Application..."));
connect(m_attachRemoteAction, SIGNAL(triggered()),
this, SLOT(attachRemoteApplication()));
m_continueAction = new QAction(this);
m_continueAction->setText(tr("Continue"));
m_continueAction->setIcon(QIcon(":/gdbdebugger/images/debugger_continue_small.png"));
......@@ -437,7 +443,7 @@ QList<Core::IOptionsPage*> DebuggerManager::initializeEngines(const QStringList
{
QList<Core::IOptionsPage*> rc;
gdbEngine = createGdbEngine(this, &rc);
const bool cdbDisabled = arguments.contains(QLatin1String("-disable-cdb"));
const bool cdbDisabled = arguments.contains(_("-disable-cdb"));
winEngine = createWinEngine(this, cdbDisabled, &rc);
scriptEngine = createScriptEngine(this, &rc);
setDebuggerType(GdbDebugger);
......@@ -810,12 +816,18 @@ void DebuggerManager::attachCore()
emit debuggingFinished();
}
void DebuggerManager::attachRemoteApplication()
{
if (!startNewDebugger(AttachRemote))
emit debuggingFinished();
}
// Figure out the debugger type of an executable
static bool determineDebuggerType(const QString &executable,
DebuggerManager::DebuggerType *dt,
QString *errorMessage)
{
if (executable.endsWith(QLatin1String(".js"))) {
if (executable.endsWith(_(".js"))) {
*dt = DebuggerManager::ScriptDebugger;
return true;
}
......@@ -869,21 +881,21 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
case StartExternal: {
StartExternalDialog dlg(mainWindow());
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
configValue(_("LastExternalExecutableFile")).toString());
dlg.setExecutableArguments(
configValue(QLatin1String("LastExternalExecutableArguments")).toString());
configValue(_("LastExternalExecutableArguments")).toString());
if (dlg.exec() != QDialog::Accepted)
return false;
setConfigValue(QLatin1String("LastExternalExecutableFile"),
setConfigValue(_("LastExternalExecutableFile"),
dlg.executableFile());
setConfigValue(QLatin1String("LastExternalExecutableArguments"),
setConfigValue(_("LastExternalExecutableArguments"),
dlg.executableArguments());
m_executable = dlg.executableFile();
m_processArgs = dlg.executableArguments().split(' ');
m_workingDir = QString();
m_attachedPID = -1;
}
break;
}
case AttachExternal: {
AttachExternalDialog dlg(mainWindow());
if (dlg.exec() != QDialog::Accepted)
......@@ -897,9 +909,9 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
tr("Cannot attach to PID 0"));
return false;
}
}
break;
case StartInternal:
}
case StartInternal: {
if (m_executable.isEmpty()) {
QString startDirectory = m_executable;
if (m_executable.isEmpty()) {
......@@ -920,30 +932,46 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
m_attachedPID = 0;
} else {
//m_executable = QDir::convertSeparators(m_executable);
//m_processArgs = sd.processArgs.join(QLatin1String(" "));
//m_processArgs = sd.processArgs.join(_(" "));
m_attachedPID = 0;
}
break;
}
case AttachCore: {
AttachCoreDialog dlg(mainWindow());
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
configValue(_("LastExternalExecutableFile")).toString());
dlg.setCoreFile(
configValue(QLatin1String("LastExternalCoreFile")).toString());
configValue(_("LastExternalCoreFile")).toString());
if (dlg.exec() != QDialog::Accepted)
return false;
setConfigValue(QLatin1String("LastExternalExecutableFile"),
setConfigValue(_("LastExternalExecutableFile"),
dlg.executableFile());
setConfigValue(QLatin1String("LastExternalCoreFile"),
setConfigValue(_("LastExternalCoreFile"),
dlg.coreFile());
m_executable = dlg.executableFile();
m_coreFile = dlg.coreFile();
m_processArgs.clear();
m_workingDir = QString();
m_attachedPID = -1;
break;
}
case AttachRemote: {
AttachRemoteDialog dlg(mainWindow());
QStringList arches;
arches.append(_("i386:x86-64:intel"));
dlg.setRemoteArchitectures(arches);
dlg.setRemoteChannel(configValue(_("LastRemoteChannel")).toString());
dlg.setRemoteArchitecture(configValue(_("LastRemoteArchtecture")).toString());
if (dlg.exec() != QDialog::Accepted)
return false;
setConfigValue(_("LastRemoteChannel"), dlg.remoteChannel());
setConfigValue(_("LastRemoteArchitecture"), dlg.remoteArchitecture());
m_remoteChannel = dlg.remoteChannel();
m_remoteArchitecture = dlg.remoteArchitecture();
break;
}
}
emit debugModeRequested();
......@@ -1218,7 +1246,7 @@ void DebuggerManager::setStatus(int status)
if (0 && !isAllowedTransition(m_status, status)) {
const QString msg = QString::fromLatin1("%1: UNEXPECTED TRANSITION: %2 -> %3").
arg(QLatin1String(Q_FUNC_INFO), QLatin1String(stateName(m_status)), QLatin1String(stateName(status)));
arg(_(Q_FUNC_INFO), _(stateName(m_status)), _(stateName(status)));
qWarning("%s", qPrintable(msg));
}
......@@ -1242,6 +1270,7 @@ void DebuggerManager::setStatus(int status)
#else
m_attachCoreAction->setEnabled(!started && !starting);
#endif
m_attachRemoteAction->setEnabled(!started && !starting);
m_watchAction->setEnabled(ready);
m_breakAction->setEnabled(true);
......@@ -1535,7 +1564,7 @@ void DebuggerManager::showQtDumperLibraryWarning(const QString &details)
dialog.setDetailedText(details);
dialog.exec();
if (dialog.clickedButton() == qtPref) {
Core::ICore::instance()->showOptionsDialog(QLatin1String("Qt4"), QLatin1String("Qt Versions"));
Core::ICore::instance()->showOptionsDialog(_("Qt4"), _("Qt Versions"));
} else if (dialog.clickedButton() == helperOff) {
theDebuggerAction(UseDebuggingHelpers)->setValue(qVariantFromValue(false), false);
}
......
......@@ -111,7 +111,8 @@ enum DebuggerStartMode
StartInternal, // Start current start project's binary
StartExternal, // Start binary found in file system
AttachExternal, // Attach to running process
AttachCore // Attach to a core file
AttachCore, // Attach to a core file
AttachRemote // Attach to a remote process
};
class IDebuggerEngine;
......@@ -225,6 +226,7 @@ public slots:
void startExternalApplication();
void attachExternalApplication();
void attachCore();
void attachRemoteApplication();
void jumpToLineExec();
void runToLineExec();
......@@ -358,6 +360,8 @@ public:
QString m_dumperLib;
int m_attachedPID;
bool m_useTerminal;
QString m_remoteChannel;
QString m_remoteArchitecture;
private:
void init();
......@@ -404,6 +408,7 @@ private:
QAction *m_startExternalAction;
QAction *m_attachExternalAction;
QAction *m_attachCoreAction;
QAction *m_attachRemoteAction;
QAction *m_continueAction;
QAction *m_stopAction;
QAction *m_resetAction; // FIXME: Should not be needed in a stable release
......
......@@ -99,6 +99,7 @@ namespace Constants {
const char * const STARTEXTERNAL = "Debugger.StartExternal";
const char * const ATTACHEXTERNAL = "Debugger.AttachExternal";
const char * const ATTACHCORE = "Debugger.AttachCore";
const char * const ATTACHREMOTE = "Debugger.AttachRemote";
const char * const RUN_TO_LINE = "Debugger.RunToLine";
const char * const RUN_TO_FUNCTION = "Debugger.RunToFunction";
......@@ -478,6 +479,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
}
#if 0
// FIXME: not yet functional
if (m_manager->m_attachRemoteAction) {
cmd = am->registerAction(m_manager->m_attachRemoteAction,
Constants::ATTACHREMOTE, globalcontext);
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
}
#endif
cmd = am->registerAction(m_manager->m_continueAction,
ProjectExplorer::Constants::DEBUG, QList<int>() << m_gdbRunningContext);
......
......@@ -92,7 +92,14 @@ Q_DECLARE_METATYPE(Debugger::Internal::GdbMi);
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define _c(s) QLatin1Char(s)
struct _c
{
inline _c(char c) : m_c(c) {}
inline operator QChar() const { return QLatin1Char(m_c); }
char m_c;
};
#define _c(c) QLatin1Char(c)
#define __(s) QLatin1String(s)
#define _(s) QString::fromLatin1(s)
......@@ -1601,6 +1608,8 @@ bool GdbEngine::startDebugger()
if (q->startMode() == AttachCore || q->startMode() == AttachExternal) {
// nothing to do
} else if (q->startMode() == AttachRemote) {
// nothing to do
} else if (q->m_useTerminal) {
m_stubProc.stop(); // We leave the console open, so recycle it now.
......@@ -1726,6 +1735,7 @@ bool GdbEngine::startDebugger()
if (q->startMode() == AttachExternal) {
sendCommand(_("attach ") + QString::number(q->m_attachedPID), GdbAttached);
qq->breakHandler()->removeAllBreakpoints();
} else if (q->startMode() == AttachCore) {
QFileInfo fi(q->m_executable);
QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
......@@ -1733,9 +1743,17 @@ bool GdbEngine::startDebugger()
// quoting core name below fails in gdb 6.8-debian
QString coreName = fi2.absoluteFilePath();
sendCommand(_("-file-exec-and-symbols ") + fileName);
sendCommand(_("target core ") + coreName, GdbTargetCore);
sendCommand(_("target core %1").arg(coreName), GdbTargetCore);
qq->breakHandler()->removeAllBreakpoints();
} else if (q->startMode() == AttachRemote) {
sendCommand(_("set architecture %1").arg(q->m_remoteArchitecture));
sendCommand(_("target remote %1").arg(q->m_remoteChannel));
qq->breakHandler()->setAllPending();
//sendCommand(_("info target"), GdbStart);
qq->notifyInferiorRunningRequested();
sendCommand(_("-exec-continue"), GdbExecContinue);
} else if (q->m_useTerminal) {
// nothing needed, stub takes care
qq->breakHandler()->setAllPending();
} else if (q->startMode() == StartInternal || q->startMode() == StartExternal) {
QFileInfo fi(q->m_executable);
QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
......@@ -1756,13 +1774,8 @@ bool GdbEngine::startDebugger()
qq->notifyInferiorRunningRequested();
sendCommand(_("-exec-run"));
#endif
}
// set all to "pending"
if (q->startMode() == AttachExternal || q->startMode() == AttachCore)
qq->breakHandler()->removeAllBreakpoints();
else if (q->startMode() == StartInternal || q->startMode() == StartExternal)
qq->breakHandler()->setAllPending();
}
return true;
}
......
......@@ -615,6 +615,9 @@ void testStdList()
flist.push_back(3);
flist.push_back(4);
foreach (Foo f, flist)
{}
std::list<bool> vec;
vec.push_back(true);
vec.push_back(false);
......
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