forked from qt-creator/qt-creator
Debugger: Add Run-in-Console for LLDB
Task-number: QTCREATORBUG-9650 Change-Id: I74586ca8c89efedbb952218497f7acdae500d3b9 Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
@@ -660,6 +660,7 @@ class Dumper(DumperBase):
|
|||||||
self.executable_ = args['executable']
|
self.executable_ = args['executable']
|
||||||
self.startMode_ = args.get('startMode', 1)
|
self.startMode_ = args.get('startMode', 1)
|
||||||
self.breakOnMain_ = args.get('breakOnMain', 0)
|
self.breakOnMain_ = args.get('breakOnMain', 0)
|
||||||
|
self.useTerminal_ = args.get('useTerminal', 0)
|
||||||
self.processArgs_ = args.get('processArgs', [])
|
self.processArgs_ = args.get('processArgs', [])
|
||||||
self.processArgs_ = map(lambda x: self.hexdecode(x), self.processArgs_)
|
self.processArgs_ = map(lambda x: self.hexdecode(x), self.processArgs_)
|
||||||
self.attachPid_ = args.get('attachPid', 0)
|
self.attachPid_ = args.get('attachPid', 0)
|
||||||
@@ -667,6 +668,8 @@ class Dumper(DumperBase):
|
|||||||
self.remoteChannel_ = args.get('remoteChannel', '')
|
self.remoteChannel_ = args.get('remoteChannel', '')
|
||||||
self.platform_ = args.get('platform', '')
|
self.platform_ = args.get('platform', '')
|
||||||
|
|
||||||
|
self.ignoreStops = 1 if self.useTerminal_ else 0
|
||||||
|
|
||||||
if self.platform_:
|
if self.platform_:
|
||||||
self.debugger.SetCurrentPlatform(self.platform_)
|
self.debugger.SetCurrentPlatform(self.platform_)
|
||||||
# sysroot has to be set *after* the platform
|
# sysroot has to be set *after* the platform
|
||||||
@@ -1259,6 +1262,9 @@ class Dumper(DumperBase):
|
|||||||
if self.isInterrupting_:
|
if self.isInterrupting_:
|
||||||
self.isInterrupting_ = False
|
self.isInterrupting_ = False
|
||||||
self.report('state="inferiorstopok"')
|
self.report('state="inferiorstopok"')
|
||||||
|
elif self.ignoreStops > 0:
|
||||||
|
self.ignoreStops -= 1
|
||||||
|
self.process.Continue()
|
||||||
else:
|
else:
|
||||||
self.report('state="stopped"')
|
self.report('state="stopped"')
|
||||||
else:
|
else:
|
||||||
|
@@ -69,6 +69,8 @@
|
|||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -90,6 +92,19 @@ LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
|
|||||||
m_lastToken = 0;
|
m_lastToken = 0;
|
||||||
setObjectName(QLatin1String("LldbEngine"));
|
setObjectName(QLatin1String("LldbEngine"));
|
||||||
|
|
||||||
|
if (startParameters.useTerminal) {
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
|
||||||
|
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
|
||||||
|
m_stubProc.setMode(Utils::ConsoleProcess::Suspend);
|
||||||
|
else
|
||||||
|
m_stubProc.setMode(Utils::ConsoleProcess::Debug);
|
||||||
|
#else
|
||||||
|
m_stubProc.setMode(Utils::ConsoleProcess::Debug);
|
||||||
|
m_stubProc.setSettings(Core::ICore::settings());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
connect(debuggerCore()->action(AutoDerefPointers), SIGNAL(valueChanged(QVariant)),
|
connect(debuggerCore()->action(AutoDerefPointers), SIGNAL(valueChanged(QVariant)),
|
||||||
SLOT(updateLocals()));
|
SLOT(updateLocals()));
|
||||||
connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()),
|
connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()),
|
||||||
@@ -103,7 +118,10 @@ LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LldbEngine::~LldbEngine()
|
LldbEngine::~LldbEngine()
|
||||||
{}
|
{
|
||||||
|
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages)
|
void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages)
|
||||||
{
|
{
|
||||||
@@ -136,6 +154,8 @@ void LldbEngine::shutdownEngine()
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
|
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
|
||||||
m_lldbProc.kill();
|
m_lldbProc.kill();
|
||||||
|
if (startParameters().useTerminal)
|
||||||
|
m_stubProc.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LldbEngine::abortDebugger()
|
void LldbEngine::abortDebugger()
|
||||||
@@ -151,13 +171,67 @@ void LldbEngine::abortDebugger()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Merge with GdbEngine/QtcProcess
|
||||||
|
bool LldbEngine::prepareCommand()
|
||||||
|
{
|
||||||
|
if (HostOsInfo::isWindowsHost()) {
|
||||||
|
DebuggerStartParameters &sp = startParameters();
|
||||||
|
QtcProcess::SplitError perr;
|
||||||
|
sp.processArgs = QtcProcess::prepareArgs(sp.processArgs, &perr,
|
||||||
|
Utils::HostOsInfo::hostOs(),
|
||||||
|
&sp.environment, &sp.workingDirectory).toWindowsArgs();
|
||||||
|
if (perr != Utils::QtcProcess::SplitOk) {
|
||||||
|
// perr == BadQuoting is never returned on Windows
|
||||||
|
// FIXME? QTCREATORBUG-2809
|
||||||
|
notifyEngineSetupFailed();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void LldbEngine::setupEngine()
|
void LldbEngine::setupEngine()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
if (startParameters().useTerminal) {
|
||||||
if (startParameters().remoteSetupNeeded)
|
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||||
notifyEngineRequestRemoteSetup();
|
showMessage(_("TRYING TO START ADAPTER"));
|
||||||
else
|
|
||||||
startLldb();
|
// Currently, adapters are not re-used
|
||||||
|
// // We leave the console open, so recycle it now.
|
||||||
|
// m_stubProc.blockSignals(true);
|
||||||
|
// m_stubProc.stop();
|
||||||
|
// m_stubProc.blockSignals(false);
|
||||||
|
|
||||||
|
if (!prepareCommand()) {
|
||||||
|
notifyEngineSetupFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_stubProc.setWorkingDirectory(startParameters().workingDirectory);
|
||||||
|
// Set environment + dumper preload.
|
||||||
|
m_stubProc.setEnvironment(startParameters().environment);
|
||||||
|
|
||||||
|
connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
|
||||||
|
connect(&m_stubProc, SIGNAL(processStarted()), SLOT(stubStarted()));
|
||||||
|
connect(&m_stubProc, SIGNAL(stubStopped()), SLOT(stubExited()));
|
||||||
|
// FIXME: Starting the stub implies starting the inferior. This is
|
||||||
|
// fairly unclean as far as the state machine and error reporting go.
|
||||||
|
|
||||||
|
if (!m_stubProc.start(startParameters().executable,
|
||||||
|
startParameters().processArgs)) {
|
||||||
|
// Error message for user is delivered via a signal.
|
||||||
|
//handleAdapterStartFailed(QString());
|
||||||
|
notifyEngineSetupFailed();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||||
|
if (startParameters().remoteSetupNeeded)
|
||||||
|
notifyEngineRequestRemoteSetup();
|
||||||
|
else
|
||||||
|
startLldb();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LldbEngine::startLldb()
|
void LldbEngine::startLldb()
|
||||||
@@ -207,27 +281,44 @@ void LldbEngine::setupInferior()
|
|||||||
|
|
||||||
Command cmd("setupInferior");
|
Command cmd("setupInferior");
|
||||||
cmd.arg("executable", executable);
|
cmd.arg("executable", executable);
|
||||||
cmd.arg("startMode", sp.startMode); // directly relying on this is brittle wrt. insertions, so check it here
|
|
||||||
cmd.arg("breakOnMain", sp.breakOnMain);
|
cmd.arg("breakOnMain", sp.breakOnMain);
|
||||||
|
cmd.arg("useTerminal", sp.useTerminal);
|
||||||
|
|
||||||
cmd.beginList("processArgs");
|
cmd.beginList("processArgs");
|
||||||
foreach (const QString &arg, args.toUnixArgs())
|
foreach (const QString &arg, args.toUnixArgs())
|
||||||
cmd.arg(arg.toUtf8().toHex());
|
cmd.arg(arg.toUtf8().toHex());
|
||||||
cmd.endList();
|
cmd.endList();
|
||||||
|
|
||||||
// it is better not to check the start mode on the python sid (as we would have to duplicate the
|
if (sp.useTerminal) {
|
||||||
// enum values), and thus we assume that if the sp.attachPID is valid we really have to attach
|
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||||
QTC_CHECK(sp.attachPID <= 0 || (sp.startMode == AttachCrashedExternal
|
const qint64 attachedPID = m_stubProc.applicationPID();
|
||||||
|| sp.startMode == AttachExternal));
|
const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID();
|
||||||
cmd.arg("attachPid", sp.attachPID);
|
const QString msg = (attachedMainThreadID != -1)
|
||||||
cmd.arg("sysRoot", sp.deviceSymbolsRoot.isEmpty() ? sp.sysRoot : sp.deviceSymbolsRoot);
|
? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
|
||||||
cmd.arg("remoteChannel", ((sp.startMode == AttachToRemoteProcess
|
: QString::fromLatin1("Attaching to %1").arg(attachedPID);
|
||||||
|| sp.startMode == AttachToRemoteServer)
|
showMessage(msg, LogMisc);
|
||||||
? sp.remoteChannel : QString()));
|
cmd.arg("startMode", AttachExternal);
|
||||||
cmd.arg("platform", sp.platform);
|
cmd.arg("attachPid", attachedPID);
|
||||||
QTC_CHECK(!sp.continueAfterAttach || (sp.startMode == AttachToRemoteProcess
|
|
||||||
|| sp.startMode == AttachExternal
|
} else {
|
||||||
|| sp.startMode == AttachToRemoteServer));
|
|
||||||
m_continueAtNextSpontaneousStop = false;
|
cmd.arg("startMode", sp.startMode);
|
||||||
|
// it is better not to check the start mode on the python sid (as we would have to duplicate the
|
||||||
|
// enum values), and thus we assume that if the sp.attachPID is valid we really have to attach
|
||||||
|
QTC_CHECK(sp.attachPID <= 0 || (sp.startMode == AttachCrashedExternal
|
||||||
|
|| sp.startMode == AttachExternal));
|
||||||
|
cmd.arg("attachPid", sp.attachPID);
|
||||||
|
cmd.arg("sysRoot", sp.deviceSymbolsRoot.isEmpty() ? sp.sysRoot : sp.deviceSymbolsRoot);
|
||||||
|
cmd.arg("remoteChannel", ((sp.startMode == AttachToRemoteProcess
|
||||||
|
|| sp.startMode == AttachToRemoteServer)
|
||||||
|
? sp.remoteChannel : QString()));
|
||||||
|
cmd.arg("platform", sp.platform);
|
||||||
|
QTC_CHECK(!sp.continueAfterAttach || (sp.startMode == AttachToRemoteProcess
|
||||||
|
|| sp.startMode == AttachExternal
|
||||||
|
|| sp.startMode == AttachToRemoteServer));
|
||||||
|
m_continueAtNextSpontaneousStop = false;
|
||||||
|
}
|
||||||
|
|
||||||
runCommand(cmd);
|
runCommand(cmd);
|
||||||
updateLocals(); // update display options
|
updateLocals(); // update display options
|
||||||
}
|
}
|
||||||
@@ -1356,5 +1447,25 @@ void LldbEngine::Command::endGroup() const
|
|||||||
args += "},";
|
args += "},";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LldbEngine::stubStarted()
|
||||||
|
{
|
||||||
|
startLldb();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LldbEngine::stubError(const QString &msg)
|
||||||
|
{
|
||||||
|
showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LldbEngine::stubExited()
|
||||||
|
{
|
||||||
|
if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
|
||||||
|
showMessage(_("STUB EXITED EXPECTEDLY"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
showMessage(_("STUB EXITED"));
|
||||||
|
notifyEngineIll();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
@@ -35,6 +35,8 @@
|
|||||||
#include <debugger/memoryagent.h>
|
#include <debugger/memoryagent.h>
|
||||||
#include <debugger/watchhandler.h>
|
#include <debugger/watchhandler.h>
|
||||||
|
|
||||||
|
#include <utils/consoleprocess.h>
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QQueue>
|
#include <QQueue>
|
||||||
@@ -211,6 +213,13 @@ private:
|
|||||||
QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
|
QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
|
||||||
|
|
||||||
void showToolTip();
|
void showToolTip();
|
||||||
|
|
||||||
|
// Console handling.
|
||||||
|
Q_SLOT void stubError(const QString &msg);
|
||||||
|
Q_SLOT void stubExited();
|
||||||
|
Q_SLOT void stubStarted();
|
||||||
|
bool prepareCommand();
|
||||||
|
Utils::ConsoleProcess m_stubProc;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user