forked from qt-creator/qt-creator
Debugger[new CDB]: Polish options, add remote debugging.
This commit is contained in:
@@ -221,9 +221,11 @@ STDMETHODIMP EventCallback::ExitProcess(
|
|||||||
{
|
{
|
||||||
ExtensionContext::instance().report('E', 0, eventContextC, "Process exited (%lu)",
|
ExtensionContext::instance().report('E', 0, eventContextC, "Process exited (%lu)",
|
||||||
ExitCode);
|
ExitCode);
|
||||||
|
const HRESULT hr = m_wrapped ? m_wrapped->ExitProcess(ExitCode) : S_OK;
|
||||||
dprintf("%s ExitProcess %u\n", creatorOutputPrefixC, ExitCode);
|
// Remotely debugged process exited, there is no session-inactive notification.
|
||||||
return m_wrapped ? m_wrapped->ExitProcess(ExitCode) : S_OK;
|
// Note: We get deleted here, so, order is important.
|
||||||
|
ExtensionContext::instance().unhookCallbacks();
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP EventCallback::LoadModule(
|
STDMETHODIMP EventCallback::LoadModule(
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ public:
|
|||||||
// Call this from the first extension command that gets a client.
|
// Call this from the first extension command that gets a client.
|
||||||
// Does not work when called from initialization.
|
// Does not work when called from initialization.
|
||||||
void hookCallbacks(CIDebugClient *client);
|
void hookCallbacks(CIDebugClient *client);
|
||||||
|
// Undo hooking.
|
||||||
|
void unhookCallbacks();
|
||||||
|
|
||||||
// Report output in standardized format understood by Qt Creator.
|
// Report output in standardized format understood by Qt Creator.
|
||||||
// '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
|
// '<qtcreatorcdbext>|R|<token>|<serviceName>|<one-line-output>'.
|
||||||
@@ -81,7 +83,6 @@ public:
|
|||||||
void setStopReason(const StopReasonMap &, const std::string &reason = std::string());
|
void setStopReason(const StopReasonMap &, const std::string &reason = std::string());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void unhookCallbacks();
|
|
||||||
bool isInitialized() const;
|
bool isInitialized() const;
|
||||||
void discardSymbolGroup();
|
void discardSymbolGroup();
|
||||||
|
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ modules
|
|||||||
idle
|
idle
|
||||||
help
|
help
|
||||||
memory
|
memory
|
||||||
|
shutdownex
|
||||||
KnownStructOutput
|
KnownStructOutput
|
||||||
|
|||||||
@@ -351,6 +351,15 @@ extern "C" HRESULT CALLBACK memory(CIDebugClient *Client, PCSTR argsIn)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extension command 'shutdownex' (shutdown is reserved):
|
||||||
|
// Unhook the output callbacks. This is normally done by the session
|
||||||
|
// inaccessible notification, however, this does not work for remote-controlled sessions.
|
||||||
|
extern "C" HRESULT CALLBACK shutdownex(CIDebugClient *, PCSTR)
|
||||||
|
{
|
||||||
|
ExtensionContext::instance().unhookCallbacks();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Hook for dumping Known Structs. Not currently used.
|
// Hook for dumping Known Structs. Not currently used.
|
||||||
// Shows up in 'dv' as well as IDebugSymbolGroup::GetValueText.
|
// Shows up in 'dv' as well as IDebugSymbolGroup::GetValueText.
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <utils/synchronousprocess.h>
|
||||||
#include <utils/winutils.h>
|
#include <utils/winutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/savedaction.h>
|
#include <utils/savedaction.h>
|
||||||
@@ -228,7 +229,6 @@ static inline bool validMode(DebuggerStartMode sm)
|
|||||||
case NoStartMode:
|
case NoStartMode:
|
||||||
case AttachTcf:
|
case AttachTcf:
|
||||||
case AttachCore:
|
case AttachCore:
|
||||||
case AttachToRemote:
|
|
||||||
case StartRemoteGdb:
|
case StartRemoteGdb:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@@ -334,7 +334,7 @@ void CdbEngine::setupEngine()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine full path to the CDB extension library.
|
// Determine full path to the CDB extension library.
|
||||||
static inline QString extensionLibraryName(bool is64Bit)
|
QString CdbEngine::extensionLibraryName(bool is64Bit)
|
||||||
{
|
{
|
||||||
// Determine extension lib name and path to use
|
// Determine extension lib name and path to use
|
||||||
QString rc;
|
QString rc;
|
||||||
@@ -387,18 +387,24 @@ bool CdbEngine::doSetupEngine(QString *errorMessage)
|
|||||||
// Determine extension lib name and path to use
|
// Determine extension lib name and path to use
|
||||||
// The extension is passed as relative name with the path variable set
|
// The extension is passed as relative name with the path variable set
|
||||||
//(does not work with absolute path names)
|
//(does not work with absolute path names)
|
||||||
const QFileInfo extensionFi(extensionLibraryName(m_options->is64bit));
|
const QFileInfo extensionFi(CdbEngine::extensionLibraryName(m_options->is64bit));
|
||||||
if (!extensionFi.isFile()) {
|
if (!extensionFi.isFile()) {
|
||||||
*errorMessage = QString::fromLatin1("Internal error: The extension %1 cannot be found.").
|
*errorMessage = QString::fromLatin1("Internal error: The extension %1 cannot be found.").
|
||||||
arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath()));
|
arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
const QString extensionFileName = extensionFi.fileName();
|
||||||
// Prepare arguments
|
// Prepare arguments
|
||||||
const DebuggerStartParameters &sp = startParameters();
|
const DebuggerStartParameters &sp = startParameters();
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
|
const bool isRemote = sp.startMode == AttachToRemote;
|
||||||
|
if (isRemote) { // Must be first
|
||||||
|
arguments << QLatin1String("-remote") << sp.remoteChannel;
|
||||||
|
} else {
|
||||||
|
arguments << (QLatin1String("-a") + extensionFileName);
|
||||||
|
}
|
||||||
// Source line info/No terminal breakpoint / Pull extension
|
// Source line info/No terminal breakpoint / Pull extension
|
||||||
arguments << QLatin1String("-lines") << QLatin1String("-G")
|
arguments << QLatin1String("-lines") << QLatin1String("-G")
|
||||||
<< (QLatin1String("-a") + extensionFi.fileName())
|
|
||||||
// register idle (debuggee stop) notification
|
// register idle (debuggee stop) notification
|
||||||
<< QLatin1String("-c")
|
<< QLatin1String("-c")
|
||||||
<< QString::fromAscii(".idle_cmd " + m_extensionCommandPrefixBA + "idle");
|
<< QString::fromAscii(".idle_cmd " + m_extensionCommandPrefixBA + "idle");
|
||||||
@@ -413,8 +419,10 @@ bool CdbEngine::doSetupEngine(QString *errorMessage)
|
|||||||
case StartExternal:
|
case StartExternal:
|
||||||
arguments << QDir::toNativeSeparators(sp.executable);
|
arguments << QDir::toNativeSeparators(sp.executable);
|
||||||
break;
|
break;
|
||||||
|
case AttachToRemote:
|
||||||
|
break;
|
||||||
case AttachExternal:
|
case AttachExternal:
|
||||||
case AttachCrashedExternal: // @TODO: event handle for crashed?
|
case AttachCrashedExternal:
|
||||||
arguments << QLatin1String("-p") << QString::number(sp.attachPID);
|
arguments << QLatin1String("-p") << QString::number(sp.attachPID);
|
||||||
if (sp.startMode == AttachCrashedExternal)
|
if (sp.startMode == AttachCrashedExternal)
|
||||||
arguments << QLatin1String("-e") << sp.crashParameter << QLatin1String("-g");
|
arguments << QLatin1String("-e") << sp.crashParameter << QLatin1String("-g");
|
||||||
@@ -451,17 +459,28 @@ bool CdbEngine::doSetupEngine(QString *errorMessage)
|
|||||||
showMessage(QString::fromLatin1("%1 running as %2").
|
showMessage(QString::fromLatin1("%1 running as %2").
|
||||||
arg(QDir::toNativeSeparators(executable)).arg(pid), LogMisc);
|
arg(QDir::toNativeSeparators(executable)).arg(pid), LogMisc);
|
||||||
m_hasDebuggee = true;
|
m_hasDebuggee = true;
|
||||||
|
if (isRemote) { // We do not get an 'idle' in a remote session, but are accessible
|
||||||
|
m_accessible = true;
|
||||||
|
const QByteArray loadCommand = QByteArray(".load ")
|
||||||
|
+ extensionFileName.toLocal8Bit();
|
||||||
|
postCommand(loadCommand, 0);
|
||||||
|
notifyEngineSetupOk();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbEngine::setupInferior()
|
void CdbEngine::setupInferior()
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug("setupInferior");
|
||||||
attemptBreakpointSynchronization();
|
attemptBreakpointSynchronization();
|
||||||
postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
|
postExtensionCommand("pid", QByteArray(), 0, &CdbEngine::handlePid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbEngine::runEngine()
|
void CdbEngine::runEngine()
|
||||||
{
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug("runEngine");
|
||||||
postCommand("g", 0);
|
postCommand("g", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +496,11 @@ void CdbEngine::shutdownInferior()
|
|||||||
notifyInferiorShutdownOk();
|
notifyInferiorShutdownOk();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!canInterruptInferior()) {
|
||||||
|
notifyInferiorShutdownFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_accessible) {
|
if (m_accessible) {
|
||||||
if (startParameters().startMode == AttachExternal || startParameters().startMode == AttachCrashedExternal)
|
if (startParameters().startMode == AttachExternal || startParameters().startMode == AttachCrashedExternal)
|
||||||
detachDebugger();
|
detachDebugger();
|
||||||
@@ -513,9 +537,20 @@ void CdbEngine::shutdownEngine()
|
|||||||
if (m_accessible) {
|
if (m_accessible) {
|
||||||
if (startParameters().startMode == AttachExternal)
|
if (startParameters().startMode == AttachExternal)
|
||||||
detachDebugger();
|
detachDebugger();
|
||||||
|
// Remote requires a bit more force to quit.
|
||||||
|
if (startParameters().startMode == AttachToRemote) {
|
||||||
|
postCommand(m_extensionCommandPrefixBA + "shutdownex", 0);
|
||||||
|
postCommand("qq", 0);
|
||||||
|
} else {
|
||||||
postCommand("q", 0);
|
postCommand("q", 0);
|
||||||
|
}
|
||||||
m_notifyEngineShutdownOnTermination = true;
|
m_notifyEngineShutdownOnTermination = true;
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
// Remote process. No can do, currently
|
||||||
|
m_notifyEngineShutdownOnTermination = true;
|
||||||
|
Utils::SynchronousProcess::stopProcess(m_process);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// Lost debuggee, debugger should quit anytime now
|
// Lost debuggee, debugger should quit anytime now
|
||||||
if (!m_hasDebuggee) {
|
if (!m_hasDebuggee) {
|
||||||
@@ -638,9 +673,21 @@ void CdbEngine::doContinueInferior()
|
|||||||
postCommand(QByteArray("g"), 0);
|
postCommand(QByteArray("g"), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CdbEngine::canInterruptInferior() const
|
||||||
|
{
|
||||||
|
return startParameters().startMode != AttachToRemote;
|
||||||
|
}
|
||||||
|
|
||||||
void CdbEngine::interruptInferior()
|
void CdbEngine::interruptInferior()
|
||||||
{
|
{
|
||||||
|
if (canInterruptInferior()) {
|
||||||
doInterruptInferior(NoSpecialStop);
|
doInterruptInferior(NoSpecialStop);
|
||||||
|
} else {
|
||||||
|
showMessage(tr("Interrupting is not possible in remote sessions."), LogError);
|
||||||
|
notifyInferiorStopOk();
|
||||||
|
notifyInferiorRunRequested();
|
||||||
|
notifyInferiorRunOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbEngine::doInterruptInferior(SpecialStopMode sm)
|
void CdbEngine::doInterruptInferior(SpecialStopMode sm)
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public:
|
|||||||
virtual void reloadSourceFiles();
|
virtual void reloadSourceFiles();
|
||||||
virtual void reloadFullStack();
|
virtual void reloadFullStack();
|
||||||
|
|
||||||
//virtual bool isSynchronous() const { return true; }
|
static QString extensionLibraryName(bool is64Bit);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readyReadStandardOut();
|
void readyReadStandardOut();
|
||||||
@@ -151,6 +151,7 @@ private:
|
|||||||
void doContinueInferior();
|
void doContinueInferior();
|
||||||
inline void parseOutputLine(QByteArray line);
|
inline void parseOutputLine(QByteArray line);
|
||||||
inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
|
inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
|
||||||
|
bool canInterruptInferior() const;
|
||||||
|
|
||||||
// Builtin commands
|
// Builtin commands
|
||||||
void dummyHandler(const CdbBuiltinCommandPtr &);
|
void dummyHandler(const CdbBuiltinCommandPtr &);
|
||||||
|
|||||||
@@ -30,15 +30,23 @@
|
|||||||
#include "cdboptionspage2.h"
|
#include "cdboptionspage2.h"
|
||||||
#include "cdboptions2.h"
|
#include "cdboptions2.h"
|
||||||
#include "debuggerconstants.h"
|
#include "debuggerconstants.h"
|
||||||
|
#include "cdbengine2.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include <utils/winutils.h>
|
# include <utils/winutils.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
|
#include <QtCore/QFileInfo>
|
||||||
|
#include <QtCore/QDir>
|
||||||
|
#include <QtCore/QDateTime>
|
||||||
#include <QtCore/QTextStream>
|
#include <QtCore/QTextStream>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
#include <QtCore/QProcess>
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
#include <QtGui/QDesktopServices>
|
#include <QtGui/QDesktopServices>
|
||||||
|
|
||||||
@@ -66,7 +74,7 @@ static inline QString msgPathConfigNote()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
|
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent), m_reportTimer(0)
|
||||||
{
|
{
|
||||||
m_ui.setupUi(this);
|
m_ui.setupUi(this);
|
||||||
m_ui.noteLabel->setText(msgPathConfigNote());
|
m_ui.noteLabel->setText(msgPathConfigNote());
|
||||||
@@ -75,10 +83,9 @@ CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
|
|||||||
|
|
||||||
m_ui.pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
m_ui.pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||||
m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
|
m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
|
||||||
m_ui.failureLabel->setVisible(false);
|
m_ui.cdbPathGroupBox->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CdbOptionsPageWidget::setOptions(CdbOptions &o)
|
void CdbOptionsPageWidget::setOptions(CdbOptions &o)
|
||||||
{
|
{
|
||||||
m_ui.pathChooser->setPath(o.executable);
|
m_ui.pathChooser->setPath(o.executable);
|
||||||
@@ -88,17 +95,33 @@ void CdbOptionsPageWidget::setOptions(CdbOptions &o)
|
|||||||
m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
|
m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CdbOptionsPageWidget::is64Bit() const
|
||||||
|
{
|
||||||
|
return m_ui.is64BitCheckBox->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CdbOptionsPageWidget::path() const
|
||||||
|
{
|
||||||
|
return m_ui.pathChooser->path();
|
||||||
|
}
|
||||||
|
|
||||||
CdbOptions CdbOptionsPageWidget::options() const
|
CdbOptions CdbOptionsPageWidget::options() const
|
||||||
{
|
{
|
||||||
CdbOptions rc;
|
CdbOptions rc;
|
||||||
rc.executable = m_ui.pathChooser->path();
|
rc.executable = path();
|
||||||
rc.enabled = m_ui.cdbPathGroupBox->isChecked();
|
rc.enabled = m_ui.cdbPathGroupBox->isChecked();
|
||||||
rc.is64bit = m_ui.is64BitCheckBox->isChecked();
|
rc.is64bit = is64Bit();
|
||||||
rc.symbolPaths = m_ui.symbolPathListEditor->pathList();
|
rc.symbolPaths = m_ui.symbolPathListEditor->pathList();
|
||||||
rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
|
rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CdbOptionsPageWidget::hideReportLabel()
|
||||||
|
{
|
||||||
|
m_ui.reportLabel->clear();
|
||||||
|
m_ui.reportLabel->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
void CdbOptionsPageWidget::autoDetect()
|
void CdbOptionsPageWidget::autoDetect()
|
||||||
{
|
{
|
||||||
QString executable;
|
QString executable;
|
||||||
@@ -109,6 +132,10 @@ void CdbOptionsPageWidget::autoDetect()
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
m_ui.is64BitCheckBox->setChecked(is64bit);
|
m_ui.is64BitCheckBox->setChecked(is64bit);
|
||||||
m_ui.pathChooser->setPath(executable);
|
m_ui.pathChooser->setPath(executable);
|
||||||
|
QString report;
|
||||||
|
// Now check for the extension library as well.
|
||||||
|
const bool allOk = checkInstallation(executable, is64Bit(), &report);
|
||||||
|
setReport(report, allOk);
|
||||||
} else {
|
} else {
|
||||||
const QString msg = tr("\"Debugging Tools for Windows\" could not be found.");
|
const QString msg = tr("\"Debugging Tools for Windows\" could not be found.");
|
||||||
const QString details = tr("Checked:\n%1").arg(checkedDirectories.join(QString(QLatin1Char('\n'))));
|
const QString details = tr("Checked:\n%1").arg(checkedDirectories.join(QString(QLatin1Char('\n'))));
|
||||||
@@ -118,10 +145,23 @@ void CdbOptionsPageWidget::autoDetect()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbOptionsPageWidget::setFailureMessage(const QString &msg)
|
void CdbOptionsPageWidget::setReport(const QString &msg, bool success)
|
||||||
{
|
{
|
||||||
m_ui.failureLabel->setText(msg);
|
// Hide label after some interval
|
||||||
m_ui.failureLabel->setVisible(!msg.isEmpty());
|
if (!m_reportTimer) {
|
||||||
|
m_reportTimer = new QTimer(this);
|
||||||
|
m_reportTimer->setSingleShot(true);
|
||||||
|
connect(m_reportTimer, SIGNAL(timeout()), this, SLOT(hideReportLabel()));
|
||||||
|
} else {
|
||||||
|
if (m_reportTimer->isActive())
|
||||||
|
m_reportTimer->stop();
|
||||||
|
}
|
||||||
|
m_reportTimer->setInterval(success ? 10000 : 20000);
|
||||||
|
m_reportTimer->start();
|
||||||
|
|
||||||
|
m_ui.reportLabel->setText(msg);
|
||||||
|
m_ui.reportLabel->setStyleSheet(success ? QString() : QString::fromAscii("background-color : 'red'"));
|
||||||
|
m_ui.reportLabel->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbOptionsPageWidget::downLoadLinkActivated(const QString &link)
|
void CdbOptionsPageWidget::downLoadLinkActivated(const QString &link)
|
||||||
@@ -138,6 +178,62 @@ QString CdbOptionsPageWidget::searchKeywords() const
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString cdbVersion(const QString &executable)
|
||||||
|
{
|
||||||
|
QProcess cdb;
|
||||||
|
cdb.start(executable, QStringList(QLatin1String("-version")));
|
||||||
|
cdb.closeWriteChannel();
|
||||||
|
if (!cdb.waitForStarted())
|
||||||
|
return QString();
|
||||||
|
if (!cdb.waitForFinished()) {
|
||||||
|
Utils::SynchronousProcess::stopProcess(cdb);
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return QString::fromLocal8Bit(cdb.readAllStandardOutput());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CdbOptionsPageWidget::checkInstallation(const QString &executable,
|
||||||
|
bool is64Bit, QString *message)
|
||||||
|
{
|
||||||
|
// 1) Check on executable
|
||||||
|
unsigned checkedItems = 0;
|
||||||
|
QString rc;
|
||||||
|
if (executable.isEmpty()) {
|
||||||
|
message->append(tr("No cdb executable specified.\n"));
|
||||||
|
} else {
|
||||||
|
const QString version = cdbVersion(executable);
|
||||||
|
if (version.isEmpty()) {
|
||||||
|
message->append(tr("Unable to determine version of %1.\n").
|
||||||
|
arg(executable));
|
||||||
|
} else {
|
||||||
|
message->append(tr("Version: %1").arg(version));
|
||||||
|
checkedItems++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Check on extension library
|
||||||
|
const QFileInfo extensionFi(CdbEngine::extensionLibraryName(is64Bit));
|
||||||
|
if (extensionFi.isFile()) {
|
||||||
|
message->append(tr("Extension library: %1, built: %3.\n").
|
||||||
|
arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath())).
|
||||||
|
arg(extensionFi.lastModified().toString(Qt::SystemLocaleShortDate)));
|
||||||
|
checkedItems++;
|
||||||
|
} else {
|
||||||
|
message->append("Extension library not found.\n");
|
||||||
|
}
|
||||||
|
return checkedItems == 2u;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CdbOptionsPageWidget::eventFilter(QObject *o, QEvent *e)
|
||||||
|
{
|
||||||
|
if (o != m_ui.cdbPathGroupBox || e->type() != QEvent::ToolTip)
|
||||||
|
return QWidget::eventFilter(o, e);
|
||||||
|
QString message;
|
||||||
|
checkInstallation(path(), is64Bit(), &message);
|
||||||
|
m_ui.cdbPathGroupBox->setToolTip(message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------- CdbOptionsPage
|
// ---------- CdbOptionsPage
|
||||||
|
|
||||||
CdbOptionsPage *CdbOptionsPage::m_instance = 0;
|
CdbOptionsPage *CdbOptionsPage::m_instance = 0;
|
||||||
@@ -183,7 +279,6 @@ QWidget *CdbOptionsPage::createPage(QWidget *parent)
|
|||||||
{
|
{
|
||||||
m_widget = new CdbOptionsPageWidget(parent);
|
m_widget = new CdbOptionsPageWidget(parent);
|
||||||
m_widget->setOptions(*m_options);
|
m_widget->setOptions(*m_options);
|
||||||
m_widget->setFailureMessage(m_failureMessage);
|
|
||||||
if (m_searchKeywords.isEmpty())
|
if (m_searchKeywords.isEmpty())
|
||||||
m_searchKeywords = m_widget->searchKeywords();
|
m_searchKeywords = m_widget->searchKeywords();
|
||||||
return m_widget;
|
return m_widget;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
#include <QtCore/QSharedPointer>
|
#include <QtCore/QSharedPointer>
|
||||||
|
|
||||||
|
QT_FORWARD_DECLARE_CLASS(QTimer)
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Cdb {
|
namespace Cdb {
|
||||||
|
|
||||||
@@ -51,16 +53,25 @@ public:
|
|||||||
void setOptions(CdbOptions &o);
|
void setOptions(CdbOptions &o);
|
||||||
CdbOptions options() const;
|
CdbOptions options() const;
|
||||||
|
|
||||||
void setFailureMessage(const QString &);
|
|
||||||
|
|
||||||
QString searchKeywords() const;
|
QString searchKeywords() const;
|
||||||
|
|
||||||
|
virtual bool eventFilter(QObject *, QEvent *);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void autoDetect();
|
void autoDetect();
|
||||||
void downLoadLinkActivated(const QString &);
|
void downLoadLinkActivated(const QString &);
|
||||||
|
void hideReportLabel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void setReport(const QString &, bool success);
|
||||||
|
inline bool is64Bit() const;
|
||||||
|
inline QString path() const;
|
||||||
|
|
||||||
|
static bool checkInstallation(const QString &executable, bool is64Bit,
|
||||||
|
QString *message);
|
||||||
|
|
||||||
Ui::CdbOptionsPageWidget2 m_ui;
|
Ui::CdbOptionsPageWidget2 m_ui;
|
||||||
|
QTimer *m_reportTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CdbOptionsPage : public Core::IOptionsPage
|
class CdbOptionsPage : public Core::IOptionsPage
|
||||||
@@ -87,15 +98,12 @@ public:
|
|||||||
|
|
||||||
static QString settingsId();
|
static QString settingsId();
|
||||||
|
|
||||||
// Load failure messages can be displayed here
|
|
||||||
void setFailureMessage(const QString &msg) { m_failureMessage = msg; }
|
|
||||||
QSharedPointer<CdbOptions> options() const { return m_options; }
|
QSharedPointer<CdbOptions> options() const { return m_options; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static CdbOptionsPage *m_instance;
|
static CdbOptionsPage *m_instance;
|
||||||
const QSharedPointer<CdbOptions> m_options;
|
const QSharedPointer<CdbOptions> m_options;
|
||||||
QPointer<CdbOptionsPageWidget> m_widget;
|
QPointer<CdbOptionsPageWidget> m_widget;
|
||||||
QString m_failureMessage;
|
|
||||||
QString m_searchKeywords;
|
QString m_searchKeywords;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,19 @@
|
|||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>Debugger::Cdb::CdbOptionsPageWidget2</class>
|
<class>Debugger::Cdb::CdbOptionsPageWidget2</class>
|
||||||
<widget class="QWidget" name="Debugger::Cdb::CdbOptionsPageWidget2">
|
<widget class="QWidget" name="Debugger::Cdb::CdbOptionsPageWidget2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>135</width>
|
||||||
|
<height>246</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="cdbPathGroupBox">
|
<widget class="QGroupBox" name="cdbPathGroupBox">
|
||||||
<property name="toolTip">
|
|
||||||
<string>These options take effect at the next start of Qt Creator.</string>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string extracomment="Placeholder">CDB</string>
|
<string extracomment="Placeholder">CDB</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -92,13 +97,16 @@
|
|||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="failureLabel">
|
<widget class="QLabel" name="reportLabel">
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">background-color: 'red';</string>
|
<string notr="true"/>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -154,10 +154,14 @@ QVariant cdbIntegerValue(const QByteArray &t)
|
|||||||
return converted;
|
return converted;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse:
|
/* Parse: 64bit:
|
||||||
\code
|
\code
|
||||||
Child-SP RetAddr Call Site
|
Child-SP RetAddr Call Site
|
||||||
00000000`0012a290 00000000`70deb844 QtCored4!QString::QString+0x18 [c:\qt\src\corelib\tools\qstring.h @ 729]
|
00000000`0012a290 00000000`70deb844 QtCored4!QString::QString+0x18 [c:\qt\src\corelib\tools\qstring.h @ 729]
|
||||||
|
\endcode 32bit:
|
||||||
|
\code
|
||||||
|
ChildEBP RetAddr
|
||||||
|
0012cc68 6714d114 QtCored4!QString::QString+0xf [d:\dev\qt4.7-vs8\qt\src\corelib\tools\qstring.h @ 729]
|
||||||
\endcode */
|
\endcode */
|
||||||
|
|
||||||
static inline bool isHexDigit(char c)
|
static inline bool isHexDigit(char c)
|
||||||
@@ -168,7 +172,7 @@ static inline bool isHexDigit(char c)
|
|||||||
static inline bool parseStackFrame(QByteArray line, Debugger::Internal::StackFrame *frame)
|
static inline bool parseStackFrame(QByteArray line, Debugger::Internal::StackFrame *frame)
|
||||||
{
|
{
|
||||||
frame->clear();
|
frame->clear();
|
||||||
if (line.isEmpty() || line.startsWith("Child-SP") || !isHexDigit(line.at(0)))
|
if (line.isEmpty() || line.startsWith("Child") || !isHexDigit(line.at(0)))
|
||||||
return false;
|
return false;
|
||||||
if (line.endsWith(']')) {
|
if (line.endsWith(']')) {
|
||||||
const int sourceFilePos = line.lastIndexOf('[');
|
const int sourceFilePos = line.lastIndexOf('[');
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "debuggerdialogs.h"
|
#include "debuggerdialogs.h"
|
||||||
#include "debuggerconstants.h"
|
#include "debuggerconstants.h"
|
||||||
|
#include "cdb2/cdbengine2.h"
|
||||||
|
|
||||||
#include "ui_attachcoredialog.h"
|
#include "ui_attachcoredialog.h"
|
||||||
#include "ui_attachexternaldialog.h"
|
#include "ui_attachexternaldialog.h"
|
||||||
@@ -43,9 +44,11 @@
|
|||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
#include <utils/historycompleter.h>
|
#include <utils/historycompleter.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QProcess>
|
#include <QtCore/QProcess>
|
||||||
|
#include <QtCore/QRegExp>
|
||||||
#include <QtCore/QDir>
|
#include <QtCore/QDir>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
@@ -56,6 +59,7 @@
|
|||||||
#include <QtGui/QProxyModel>
|
#include <QtGui/QProxyModel>
|
||||||
#include <QtGui/QSortFilterProxyModel>
|
#include <QtGui/QSortFilterProxyModel>
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
|
#include <QtGui/QGroupBox>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
@@ -744,6 +748,97 @@ void StartRemoteDialog::updateState()
|
|||||||
m_ui->serverStartScript->setEnabled(enabled);
|
m_ui->serverStartScript->setEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------- StartRemoteCdbDialog
|
||||||
|
static inline QString cdbRemoteHelp()
|
||||||
|
{
|
||||||
|
const char *cdbConnectionSyntax =
|
||||||
|
"Server:Port<br>"
|
||||||
|
"tcp:server=Server,port=Port[,password=Password][,ipversion=6]\n"
|
||||||
|
"tcp:clicon=Server,port=Port[,password=Password][,ipversion=6]\n"
|
||||||
|
"npipe:server=Server,pipe=PipeName[,password=Password]\n"
|
||||||
|
"com:port=COMPort,baud=BaudRate,channel=COMChannel[,password=Password]\n"
|
||||||
|
"spipe:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,pipe=PipeName[,password=Password]\n"
|
||||||
|
"ssl:proto=Protocol,{certuser=Cert|machuser=Cert},server=Server,port=Socket[,password=Password]\n"
|
||||||
|
"ssl:proto=Protocol,{certuser=Cert|machuser=Cert},clicon=Server,port=Socket[,password=Password]";
|
||||||
|
|
||||||
|
const QString ext32 = QDir::toNativeSeparators(Debugger::Cdb::CdbEngine::extensionLibraryName(false));
|
||||||
|
const QString ext64 = QDir::toNativeSeparators(Debugger::Cdb::CdbEngine::extensionLibraryName(true));
|
||||||
|
return StartRemoteCdbDialog::tr(
|
||||||
|
"<html><body><p>The remote CDB needs to load the matching Qt Creator CDB extension "
|
||||||
|
"(<code>%1</code> or <code>%2</code>, respectively).</p><p>Copy it onto the remote machine and set the "
|
||||||
|
"environment variable <code>%3</code> to point to its folder.</p><p>"
|
||||||
|
"Launch the remote CDB as <code>%4 <executable></code> "
|
||||||
|
" to use TCP/IP as communication protocol.</p><p>Enter the connection parameters as:</p>"
|
||||||
|
"<pre>%5</pre></body></html>").
|
||||||
|
arg(ext32, ext64, QLatin1String("_NT_DEBUGGER_EXTENSION_PATH"),
|
||||||
|
QLatin1String("cdb.exe -server tcp:port=1234"),
|
||||||
|
QLatin1String(cdbConnectionSyntax));
|
||||||
|
}
|
||||||
|
|
||||||
|
StartRemoteCdbDialog::StartRemoteCdbDialog(QWidget *parent) :
|
||||||
|
QDialog(parent), m_okButton(0), m_lineEdit(new QLineEdit)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Start a CDB Remote Session"));
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
QGroupBox *groupBox = new QGroupBox;
|
||||||
|
QFormLayout *formLayout = new QFormLayout;
|
||||||
|
QLabel *helpLabel = new QLabel(cdbRemoteHelp());
|
||||||
|
helpLabel->setWordWrap(true);
|
||||||
|
helpLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
formLayout->addRow(helpLabel);
|
||||||
|
QLabel *label = new QLabel(tr("&Connection:"));
|
||||||
|
label->setBuddy(m_lineEdit);
|
||||||
|
m_lineEdit->setMinimumWidth(400);
|
||||||
|
connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
|
||||||
|
formLayout->addRow(label, m_lineEdit);
|
||||||
|
groupBox->setLayout(formLayout);
|
||||||
|
|
||||||
|
QVBoxLayout *vLayout = new QVBoxLayout;
|
||||||
|
vLayout->addWidget(groupBox);
|
||||||
|
QDialogButtonBox *box = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
|
||||||
|
vLayout->addWidget(box);
|
||||||
|
m_okButton = box->button(QDialogButtonBox::Ok);
|
||||||
|
connect(m_lineEdit, SIGNAL(returnPressed()), m_okButton, SLOT(animateClick()));
|
||||||
|
m_okButton->setEnabled(false);
|
||||||
|
connect(box, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
|
connect(box, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
|
||||||
|
setLayout(vLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRemoteCdbDialog::accept()
|
||||||
|
{
|
||||||
|
if (!m_lineEdit->text().isEmpty())
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
StartRemoteCdbDialog::~StartRemoteCdbDialog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRemoteCdbDialog::textChanged(const QString &t)
|
||||||
|
{
|
||||||
|
m_okButton->setEnabled(!t.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StartRemoteCdbDialog::connection() const
|
||||||
|
{
|
||||||
|
const QString rc = m_lineEdit->text();
|
||||||
|
// Transform an IP:POrt ('localhost:1234') specification into full spec
|
||||||
|
QRegExp ipRegexp(QLatin1String("([\\w\\.\\-_]+):([0-9]{1,4})"));
|
||||||
|
QTC_ASSERT(ipRegexp.isValid(), return QString());
|
||||||
|
if (ipRegexp.exactMatch(rc))
|
||||||
|
return QString::fromAscii("tcp:server=%1,port=%2").arg(ipRegexp.cap(1), ipRegexp.cap(2));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartRemoteCdbDialog::setConnection(const QString &c)
|
||||||
|
{
|
||||||
|
m_lineEdit->setText(c);
|
||||||
|
m_okButton->setEnabled(!c.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
AddressDialog::AddressDialog(QWidget *parent) :
|
AddressDialog::AddressDialog(QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
m_lineEdit(new QLineEdit),
|
m_lineEdit(new QLineEdit),
|
||||||
|
|||||||
@@ -200,6 +200,27 @@ private:
|
|||||||
Ui::StartRemoteDialog *m_ui;
|
Ui::StartRemoteDialog *m_ui;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StartRemoteCdbDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit StartRemoteCdbDialog(QWidget *parent);
|
||||||
|
~StartRemoteCdbDialog();
|
||||||
|
|
||||||
|
QString connection() const;
|
||||||
|
void setConnection(const QString &);
|
||||||
|
|
||||||
|
virtual void accept();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void textChanged(const QString &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPushButton *m_okButton;
|
||||||
|
QLineEdit *m_lineEdit;
|
||||||
|
};
|
||||||
|
|
||||||
class AddressDialog : public QDialog {
|
class AddressDialog : public QDialog {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -343,6 +343,7 @@ const char * const ATTACHEXTERNAL = "Debugger.AttachExternal";
|
|||||||
const char * const ATTACHCORE = "Debugger.AttachCore";
|
const char * const ATTACHCORE = "Debugger.AttachCore";
|
||||||
const char * const ATTACHTCF = "Debugger.AttachTcf";
|
const char * const ATTACHTCF = "Debugger.AttachTcf";
|
||||||
const char * const ATTACHREMOTE = "Debugger.AttachRemote";
|
const char * const ATTACHREMOTE = "Debugger.AttachRemote";
|
||||||
|
const char * const ATTACHREMOTECDB = "Debugger.AttachRemoteCDB";
|
||||||
const char * const DETACH = "Debugger.Detach";
|
const char * const DETACH = "Debugger.Detach";
|
||||||
|
|
||||||
const char * const RUN_TO_LINE1 = "Debugger.RunToLine1";
|
const char * const RUN_TO_LINE1 = "Debugger.RunToLine1";
|
||||||
@@ -971,6 +972,7 @@ public slots:
|
|||||||
|
|
||||||
void debugProject();
|
void debugProject();
|
||||||
void startExternalApplication();
|
void startExternalApplication();
|
||||||
|
void startRemoteCdbSession();
|
||||||
void startRemoteApplication();
|
void startRemoteApplication();
|
||||||
void attachExternalApplication();
|
void attachExternalApplication();
|
||||||
void attachExternalApplication
|
void attachExternalApplication
|
||||||
@@ -1243,6 +1245,7 @@ public:
|
|||||||
QAction *m_debugAction;
|
QAction *m_debugAction;
|
||||||
QAction *m_startExternalAction;
|
QAction *m_startExternalAction;
|
||||||
QAction *m_startRemoteAction;
|
QAction *m_startRemoteAction;
|
||||||
|
QAction *m_startRemoteCdbAction;
|
||||||
QAction *m_attachExternalAction;
|
QAction *m_attachExternalAction;
|
||||||
QAction *m_attachCoreAction;
|
QAction *m_attachCoreAction;
|
||||||
QAction *m_attachTcfAction;
|
QAction *m_attachTcfAction;
|
||||||
@@ -1303,8 +1306,7 @@ public:
|
|||||||
bool m_gdbBinariesChanged;
|
bool m_gdbBinariesChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) : m_startRemoteCdbAction(0)
|
||||||
DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin)
|
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!theDebuggerCore, /**/);
|
QTC_ASSERT(!theDebuggerCore, /**/);
|
||||||
theDebuggerCore = this;
|
theDebuggerCore = this;
|
||||||
@@ -1669,11 +1671,15 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
|||||||
act->setText(tr("Start and Attach to Remote Application..."));
|
act->setText(tr("Start and Attach to Remote Application..."));
|
||||||
connect(act, SIGNAL(triggered()), SLOT(startRemoteApplication()));
|
connect(act, SIGNAL(triggered()), SLOT(startRemoteApplication()));
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
m_startRemoteCdbAction = new QAction(tr("Attach to Remote CDB Session..."), this);
|
||||||
|
connect(m_startRemoteCdbAction, SIGNAL(triggered()), SLOT(startRemoteCdbSession()));
|
||||||
|
#endif
|
||||||
|
|
||||||
act = m_detachAction = new QAction(this);
|
act = m_detachAction = new QAction(this);
|
||||||
act->setText(tr("Detach Debugger"));
|
act->setText(tr("Detach Debugger"));
|
||||||
connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
|
connect(act, SIGNAL(triggered()), SLOT(handleExecDetach()));
|
||||||
|
|
||||||
|
|
||||||
Core::Command *cmd = 0;
|
Core::Command *cmd = 0;
|
||||||
|
|
||||||
Core::ActionContainer *mstart =
|
Core::ActionContainer *mstart =
|
||||||
@@ -1716,6 +1722,13 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
|
|||||||
cmd->setAttribute(Command::CA_Hide);
|
cmd->setAttribute(Command::CA_Hide);
|
||||||
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
||||||
|
|
||||||
|
if (m_startRemoteCdbAction) {
|
||||||
|
cmd = am->registerAction(m_startRemoteCdbAction,
|
||||||
|
Constants::ATTACHREMOTECDB, globalcontext);
|
||||||
|
cmd->setAttribute(Command::CA_Hide);
|
||||||
|
mstart->addAction(cmd, CC::G_DEFAULT_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
cmd = am->registerAction(m_detachAction,
|
cmd = am->registerAction(m_detachAction,
|
||||||
Constants::DETACH, globalcontext);
|
Constants::DETACH, globalcontext);
|
||||||
cmd->setAttribute(Command::CA_Hide);
|
cmd->setAttribute(Command::CA_Hide);
|
||||||
@@ -2124,6 +2137,25 @@ void DebuggerPluginPrivate::attachRemote(const QString &spec)
|
|||||||
startDebugger(rc);
|
startDebugger(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebuggerPluginPrivate::startRemoteCdbSession()
|
||||||
|
{
|
||||||
|
const QString connectionKey = _("CdbRemoteConnection");
|
||||||
|
DebuggerStartParameters sp;
|
||||||
|
sp.toolChainType = ProjectExplorer::ToolChain_MSVC;
|
||||||
|
sp.startMode = AttachToRemote;
|
||||||
|
StartRemoteCdbDialog dlg(mainWindow());
|
||||||
|
QString previousConnection = configValue(connectionKey).toString();
|
||||||
|
if (previousConnection.isEmpty())
|
||||||
|
previousConnection = QLatin1String("localhost:1234");
|
||||||
|
dlg.setConnection(previousConnection);
|
||||||
|
if (dlg.exec() != QDialog::Accepted)
|
||||||
|
return;
|
||||||
|
sp.remoteChannel = dlg.connection();
|
||||||
|
setConfigValue(connectionKey, sp.remoteChannel);
|
||||||
|
if (RunControl *rc = createDebugger(sp))
|
||||||
|
startDebugger(rc);
|
||||||
|
}
|
||||||
|
|
||||||
void DebuggerPluginPrivate::startRemoteApplication()
|
void DebuggerPluginPrivate::startRemoteApplication()
|
||||||
{
|
{
|
||||||
DebuggerStartParameters sp;
|
DebuggerStartParameters sp;
|
||||||
|
|||||||
Reference in New Issue
Block a user