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:
hjk
2014-03-03 16:59:56 +01:00
parent f18faa714d
commit a8a9786b91
3 changed files with 147 additions and 21 deletions

View File

@@ -660,6 +660,7 @@ class Dumper(DumperBase):
self.executable_ = args['executable']
self.startMode_ = args.get('startMode', 1)
self.breakOnMain_ = args.get('breakOnMain', 0)
self.useTerminal_ = args.get('useTerminal', 0)
self.processArgs_ = args.get('processArgs', [])
self.processArgs_ = map(lambda x: self.hexdecode(x), self.processArgs_)
self.attachPid_ = args.get('attachPid', 0)
@@ -667,6 +668,8 @@ class Dumper(DumperBase):
self.remoteChannel_ = args.get('remoteChannel', '')
self.platform_ = args.get('platform', '')
self.ignoreStops = 1 if self.useTerminal_ else 0
if self.platform_:
self.debugger.SetCurrentPlatform(self.platform_)
# sysroot has to be set *after* the platform
@@ -1259,6 +1262,9 @@ class Dumper(DumperBase):
if self.isInterrupting_:
self.isInterrupting_ = False
self.report('state="inferiorstopok"')
elif self.ignoreStops > 0:
self.ignoreStops -= 1
self.process.Continue()
else:
self.report('state="stopped"')
else:

View File

@@ -69,6 +69,8 @@
#include <QMessageBox>
#include <QToolTip>
using namespace Utils;
namespace Debugger {
namespace Internal {
@@ -90,6 +92,19 @@ LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
m_lastToken = 0;
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)),
SLOT(updateLocals()));
connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()),
@@ -103,7 +118,10 @@ LldbEngine::LldbEngine(const DebuggerStartParameters &startParameters)
}
LldbEngine::~LldbEngine()
{}
{
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
}
void LldbEngine::executeDebuggerCommand(const QString &command, DebuggerLanguages)
{
@@ -136,6 +154,8 @@ void LldbEngine::shutdownEngine()
{
QTC_ASSERT(state() == EngineShutdownRequested, qDebug() << state());
m_lldbProc.kill();
if (startParameters().useTerminal)
m_stubProc.stop();
}
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()
{
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
if (startParameters().remoteSetupNeeded)
notifyEngineRequestRemoteSetup();
else
startLldb();
if (startParameters().useTerminal) {
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
showMessage(_("TRYING TO START ADAPTER"));
// 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()
@@ -207,27 +281,44 @@ void LldbEngine::setupInferior()
Command cmd("setupInferior");
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("useTerminal", sp.useTerminal);
cmd.beginList("processArgs");
foreach (const QString &arg, args.toUnixArgs())
cmd.arg(arg.toUtf8().toHex());
cmd.endList();
// 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;
if (sp.useTerminal) {
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
const qint64 attachedPID = m_stubProc.applicationPID();
const qint64 attachedMainThreadID = m_stubProc.applicationMainThreadID();
const QString msg = (attachedMainThreadID != -1)
? QString::fromLatin1("Attaching to %1 (%2)").arg(attachedPID).arg(attachedMainThreadID)
: QString::fromLatin1("Attaching to %1").arg(attachedPID);
showMessage(msg, LogMisc);
cmd.arg("startMode", AttachExternal);
cmd.arg("attachPid", attachedPID);
} else {
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);
updateLocals(); // update display options
}
@@ -1356,5 +1447,25 @@ void LldbEngine::Command::endGroup() const
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 Debugger

View File

@@ -35,6 +35,8 @@
#include <debugger/memoryagent.h>
#include <debugger/watchhandler.h>
#include <utils/consoleprocess.h>
#include <QPointer>
#include <QProcess>
#include <QQueue>
@@ -211,6 +213,13 @@ private:
QScopedPointer<DebuggerToolTipContext> m_toolTipContext;
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