Commit a8a9786b authored by hjk's avatar hjk
Browse files

Debugger: Add Run-in-Console for LLDB



Task-number: QTCREATORBUG-9650
Change-Id: I74586ca8c89efedbb952218497f7acdae500d3b9
Reviewed-by: default avatarEike Ziller <eike.ziller@digia.com>
parent f18faa71
......@@ -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:
......
......@@ -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
......@@ -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
......
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