forked from qt-creator/qt-creator
Debugger: Invert LLDB/Python startup order
Instead of starting LLDB through a Python script this now starts LLDB directly. This did not work a while ago but seems fine nowaday. Change-Id: I20e915070cd6addf260817c311f4160d010aa861 Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com> Reviewed-by: hjk <hjk@theqtcompany.com>
This commit is contained in:
@@ -30,44 +30,19 @@
|
||||
|
||||
import atexit
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import select
|
||||
import sys
|
||||
import subprocess
|
||||
import threading
|
||||
import lldb
|
||||
|
||||
currentDir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
|
||||
sys.path.insert(1, currentDir)
|
||||
|
||||
from dumper import *
|
||||
|
||||
lldbCmd = 'lldb'
|
||||
if len(sys.argv) > 1:
|
||||
lldbCmd = sys.argv[1]
|
||||
|
||||
proc = subprocess.Popen(args=[lldbCmd, '-P'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(path, error) = proc.communicate()
|
||||
|
||||
if error.startswith('lldb: invalid option -- P'):
|
||||
sys.stdout.write('msg=\'Could not run "%s -P". Trying to find lldb.so from Xcode.\'@\n' % lldbCmd)
|
||||
proc = subprocess.Popen(args=['xcode-select', '--print-path'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
(path, error) = proc.communicate()
|
||||
if len(error):
|
||||
path = '/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/'
|
||||
sys.stdout.write('msg=\'Could not run "xcode-select --print-path"@\n')
|
||||
sys.stdout.write('msg=\'Using hardcoded fallback at %s\'@\n' % path)
|
||||
else:
|
||||
path = path.strip() + '/../SharedFrameworks/LLDB.framework/Versions/A/Resources/Python/'
|
||||
sys.stdout.write('msg=\'Using fallback at %s\'@\n' % path)
|
||||
|
||||
sys.path.insert(1, path.strip())
|
||||
|
||||
import lldb
|
||||
|
||||
#######################################################################
|
||||
#
|
||||
# Helpers
|
||||
@@ -667,6 +642,9 @@ class Dumper(DumperBase):
|
||||
else:
|
||||
self.target = self.debugger.CreateTarget(None, None, None, True, error)
|
||||
|
||||
if self.target.IsValid():
|
||||
self.handleBreakpoints(args)
|
||||
|
||||
state = "inferiorsetupok" if self.target.IsValid() else "inferiorsetupfailed"
|
||||
self.report('state="%s",msg="%s",exe="%s"' % (state, error, self.executable_))
|
||||
|
||||
@@ -1193,7 +1171,7 @@ class Dumper(DumperBase):
|
||||
|
||||
def report(self, stuff):
|
||||
with self.outputLock:
|
||||
sys.stdout.write(stuff + "@\n")
|
||||
sys.stdout.write("@\n" + stuff + "@\n")
|
||||
|
||||
def reportStatus(self, msg):
|
||||
self.report('statusmessage="%s"' % msg)
|
||||
@@ -1573,7 +1551,7 @@ class Dumper(DumperBase):
|
||||
self.report('success="%d",output="%s",error="%s"' % (success, output, error))
|
||||
|
||||
def addExtraDumper(self, args):
|
||||
addDumperModule(args['path'])
|
||||
self.addDumperModule(args['path'])
|
||||
self.report('ok')
|
||||
|
||||
def updateData(self, args):
|
||||
@@ -1662,14 +1640,6 @@ class Dumper(DumperBase):
|
||||
self.reportError(error)
|
||||
self.reportVariables()
|
||||
|
||||
def execute(self, args):
|
||||
getattr(self, args['cmd'])(args)
|
||||
self.report('token="%s"' % args['token'])
|
||||
if 'continuation' in args:
|
||||
cont = args['continuation']
|
||||
self.report('continuation="%s"' % cont)
|
||||
|
||||
|
||||
def convertHash(args):
|
||||
if sys.version_info[0] == 3:
|
||||
return args
|
||||
@@ -1693,36 +1663,19 @@ def convertHash(args):
|
||||
return cargs
|
||||
|
||||
|
||||
def doit():
|
||||
|
||||
db = Dumper()
|
||||
db.report('lldbversion="%s"' % lldb.SBDebugger.GetVersionString())
|
||||
db.reportState("enginesetupok")
|
||||
|
||||
line = sys.stdin.readline()
|
||||
while line:
|
||||
try:
|
||||
db.execute(convertHash(json.loads(line)))
|
||||
except:
|
||||
(exType, exValue, exTraceback) = sys.exc_info()
|
||||
showException("MAIN LOOP", exType, exValue, exTraceback)
|
||||
line = sys.stdin.readline()
|
||||
|
||||
|
||||
# Used in dumper auto test.
|
||||
# Usage: python lldbbridge.py /path/to/testbinary comma-separated-inames
|
||||
class Tester(Dumper):
|
||||
def __init__(self):
|
||||
def __init__(self, binary, expandedINames):
|
||||
Dumper.__init__(self)
|
||||
lldb.theDumper = self
|
||||
|
||||
self.expandedINames = set(sys.argv[3].split(','))
|
||||
self.expandedINames = set(expandedINames)
|
||||
self.passExceptions = True
|
||||
|
||||
self.loadDumperFiles()
|
||||
error = lldb.SBError()
|
||||
self.target = self.debugger.CreateTarget(sys.argv[2],
|
||||
None, None, True, error)
|
||||
self.target = self.debugger.CreateTarget(binary, None, None, True, error)
|
||||
|
||||
if error.GetType():
|
||||
warn("ERROR: %s" % error)
|
||||
@@ -1730,6 +1683,7 @@ class Tester(Dumper):
|
||||
|
||||
s = threading.Thread(target=self.testLoop, args=[])
|
||||
s.start()
|
||||
s.join(30)
|
||||
|
||||
def testLoop(self):
|
||||
# Disable intermediate reporting.
|
||||
@@ -1801,11 +1755,3 @@ class Tester(Dumper):
|
||||
#self.report("ENV=%s" % os.environ.items())
|
||||
#self.report("DUMPER=%s" % self.qqDumpers)
|
||||
lldb.SBDebugger.Destroy(self.debugger)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 2:
|
||||
Tester()
|
||||
else:
|
||||
doit()
|
||||
|
||||
|
@@ -129,10 +129,9 @@ void LldbEngine::runCommand(const Command &command)
|
||||
QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
|
||||
++m_lastToken;
|
||||
QByteArray token = QByteArray::number(m_lastToken);
|
||||
QByteArray cmd = "{\"cmd\":\"" + command.function + "\","
|
||||
+ command.args + "\"token\":" + token + "}\n";
|
||||
showMessage(_(token + cmd), LogInput);
|
||||
m_lldbProc.write(cmd);
|
||||
QByteArray cmd = command.function + "({" + command.args + "})";
|
||||
showMessage(_(token + cmd + '\n'), LogInput);
|
||||
m_lldbProc.write("sc db." + cmd + "\n");
|
||||
}
|
||||
|
||||
void LldbEngine::debugLastCommand()
|
||||
@@ -246,16 +245,12 @@ void LldbEngine::startLldb()
|
||||
connect(this, &LldbEngine::outputReady,
|
||||
this, &LldbEngine::handleResponse, Qt::QueuedConnection);
|
||||
|
||||
QStringList args;
|
||||
args.append(_("-i"));
|
||||
args.append(ICore::resourcePath() + _("/debugger/lldbbridge.py"));
|
||||
args.append(m_lldbCmd);
|
||||
showMessage(_("STARTING LLDB: python ") + args.join(QLatin1Char(' ')));
|
||||
showMessage(_("STARTING LLDB: ") + m_lldbCmd);
|
||||
m_lldbProc.setEnvironment(startParameters().environment.toStringList());
|
||||
if (!startParameters().workingDirectory.isEmpty())
|
||||
m_lldbProc.setWorkingDirectory(startParameters().workingDirectory);
|
||||
|
||||
m_lldbProc.start(_("python"), args);
|
||||
m_lldbProc.start(m_lldbCmd);
|
||||
|
||||
if (!m_lldbProc.waitForStarted()) {
|
||||
const QString msg = tr("Unable to start LLDB \"%1\": %2")
|
||||
@@ -265,6 +260,21 @@ void LldbEngine::startLldb()
|
||||
if (!msg.isEmpty())
|
||||
ICore::showWarningWithOptions(tr("Adapter start failed."), msg);
|
||||
}
|
||||
|
||||
showMessage(_("ADAPTER STARTED"));
|
||||
showStatusMessage(tr("Setting up inferior..."));
|
||||
|
||||
const QByteArray dumperSourcePath =
|
||||
ICore::resourcePath().toLocal8Bit() + "/debugger/";
|
||||
|
||||
m_lldbProc.write("sc sys.path.insert(1, '" + dumperSourcePath + "')\n");
|
||||
m_lldbProc.write("sc from lldbbridge import *\n");
|
||||
m_lldbProc.write("sc print(dir())\n");
|
||||
m_lldbProc.write("sc db = Dumper()\n");
|
||||
m_lldbProc.write("sc db.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString())\n");
|
||||
|
||||
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
|
||||
notifyEngineSetupOk();
|
||||
}
|
||||
|
||||
void LldbEngine::setupInferior()
|
||||
@@ -299,6 +309,8 @@ void LldbEngine::setupInferior()
|
||||
cmd.arg("useTerminal", sp.useTerminal);
|
||||
cmd.arg("startMode", sp.startMode);
|
||||
|
||||
attemptBreakpointSynchronizationHelper(&cmd);
|
||||
|
||||
cmd.beginList("processArgs");
|
||||
foreach (const QString &arg, args.toUnixArgs())
|
||||
cmd.arg(arg.toUtf8().toHex());
|
||||
@@ -338,19 +350,7 @@ void LldbEngine::setupInferior()
|
||||
|
||||
void LldbEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
|
||||
Command cmd("handleBreakpoints");
|
||||
if (attemptBreakpointSynchronizationHelper(&cmd)) {
|
||||
runEngine2();
|
||||
} else {
|
||||
cmd.arg("continuation", "runEngine2");
|
||||
runCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void LldbEngine::runEngine2()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state(); return);
|
||||
showStatusMessage(tr("Running requested..."), 5000);
|
||||
runCommand("runEngine");
|
||||
}
|
||||
@@ -446,8 +446,6 @@ void LldbEngine::handleResponse(const QByteArray &response)
|
||||
refreshDisassembly(item);
|
||||
else if (name == "memory")
|
||||
refreshMemory(item);
|
||||
else if (name == "continuation")
|
||||
runContinuation(item);
|
||||
else if (name == "full-backtrace")
|
||||
showFullBacktrace(item);
|
||||
else if (name == "statusmessage") {
|
||||
@@ -465,12 +463,6 @@ void LldbEngine::showFullBacktrace(const GdbMi &data)
|
||||
QString::fromUtf8(QByteArray::fromHex(data.data())));
|
||||
}
|
||||
|
||||
void LldbEngine::runContinuation(const GdbMi &data)
|
||||
{
|
||||
const QByteArray target = data.data();
|
||||
QMetaObject::invokeMethod(this, target, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void LldbEngine::executeRunToLine(const ContextData &data)
|
||||
{
|
||||
resetLocation();
|
||||
|
@@ -161,7 +161,6 @@ private:
|
||||
Q_SLOT void readLldbStandardOutput();
|
||||
Q_SLOT void readLldbStandardError();
|
||||
Q_SLOT void handleResponse(const QByteArray &data);
|
||||
Q_SLOT void runEngine2();
|
||||
Q_SLOT void updateAll();
|
||||
Q_SLOT void updateStack();
|
||||
Q_SLOT void updateLocals();
|
||||
@@ -184,7 +183,6 @@ private:
|
||||
void refreshAddedBreakpoint(const GdbMi &bkpts);
|
||||
void refreshChangedBreakpoint(const GdbMi &bkpts);
|
||||
void refreshRemovedBreakpoint(const GdbMi &bkpts);
|
||||
void runContinuation(const GdbMi &data);
|
||||
void showFullBacktrace(const GdbMi &data);
|
||||
|
||||
typedef void (LldbEngine::*LldbCommandContinuation)();
|
||||
|
@@ -1210,13 +1210,11 @@ void tst_Dumpers::dumper()
|
||||
expanded += iname;
|
||||
}
|
||||
|
||||
QByteArray exe;
|
||||
QByteArray exe = m_debuggerBinary;
|
||||
QStringList args;
|
||||
QByteArray cmds;
|
||||
|
||||
if (m_debuggerEngine == GdbEngine) {
|
||||
exe = m_debuggerBinary;
|
||||
|
||||
const QFileInfo gdbBinaryFile(QString::fromLatin1(exe));
|
||||
const QByteArray uninstalledData = gdbBinaryFile.absolutePath().toLocal8Bit() + "/data-directory/python";
|
||||
|
||||
@@ -1245,7 +1243,6 @@ void tst_Dumpers::dumper()
|
||||
cmds += "quit\n";
|
||||
|
||||
} else if (m_debuggerEngine == CdbEngine) {
|
||||
exe = m_debuggerBinary;
|
||||
args << QLatin1String("-aqtcreatorcdbext.dll")
|
||||
<< QLatin1String("-G")
|
||||
<< QLatin1String("-xi")
|
||||
@@ -1258,15 +1255,19 @@ void tst_Dumpers::dumper()
|
||||
cmds += "!qtcreatorcdbext.locals -t -D -e " + expanded + " -v -c 0\n"
|
||||
"q\n";
|
||||
} else if (m_debuggerEngine == LldbEngine) {
|
||||
exe = "python";
|
||||
args << QLatin1String(dumperDir + "/lldbbridge.py")
|
||||
<< QString::fromUtf8(m_debuggerBinary)
|
||||
<< t->buildPath + QLatin1String("/doit")
|
||||
<< QString::fromUtf8(expanded);
|
||||
QFile fullLldb(t->buildPath + QLatin1String("/lldbcommand.txt"));
|
||||
fullLldb.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|QFile::ReadGroup|QFile::ReadOther);
|
||||
fullLldb.open(QIODevice::WriteOnly);
|
||||
fullLldb.write(exe + ' ' + args.join(QLatin1String(" ")).toUtf8());
|
||||
fullLldb.write(exe + ' ' + args.join(QLatin1String(" ")).toUtf8() + '\n');
|
||||
|
||||
cmds = "sc import sys\n"
|
||||
"sc sys.path.insert(1, '" + dumperDir + "')\n"
|
||||
"sc from lldbbridge import *\n"
|
||||
"sc print(dir())\n"
|
||||
"sc Tester('" + t->buildPath.toLatin1() + "/doit', '" + expanded + "')\n"
|
||||
"quit\n";
|
||||
|
||||
fullLldb.write(cmds);
|
||||
fullLldb.close();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user