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.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,14 +171,68 @@ 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()
|
||||
{
|
||||
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,13 +281,28 @@ 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();
|
||||
|
||||
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
|
||||
@@ -228,6 +317,8 @@ void LldbEngine::setupInferior()
|
||||
|| 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
|
||||
|
Reference in New Issue
Block a user