diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index e3d91963451..f0083be012d 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -891,14 +891,20 @@ class Dumper(DumperBase): if (self.startMode_ == DebuggerStartMode.AttachToRemoteServer or self.startMode_ == DebuggerStartMode.AttachToRemoteProcess): - - remote_channel = 'connect://' + self.remoteChannel_ + # For some reason, 127.0.0.1 doesn't work with Android. + remote_channel = ('connect://' + + self.remoteChannel_.replace('127.0.0.1', 'localhost')) connect_options = lldb.SBPlatformConnectOptions(remote_channel) res = self.target.GetPlatform().ConnectRemote(connect_options) - DumperBase.warn("CONNECT: %s %s %s" % (res, + DumperBase.warn("CONNECT: %s %s %s %s" % (res, + remote_channel, self.target.GetPlatform().GetName(), self.target.GetPlatform().IsConnected())) + if not res.Success(): + self.report(self.describeError(error)) + self.reportState('enginerunfailed') + return broadcaster = self.target.GetBroadcaster() @@ -928,7 +934,7 @@ class Dumper(DumperBase): def prepare(self, args): error = lldb.SBError() - if self.attachPid_ > 0: + if self.attachPid_ > 0 and self.platform_ != "remote-linux": attachInfo = lldb.SBAttachInfo(self.attachPid_) self.process = self.target.Attach(attachInfo, error) if not error.Success(): @@ -944,6 +950,7 @@ class Dumper(DumperBase): self.reportState('enginerunandinferiorstopok') else: self.reportState('enginerunandinferiorrunok') + elif (self.startMode_ == DebuggerStartMode.AttachToRemoteServer or self.startMode_ == DebuggerStartMode.AttachToRemoteProcess): @@ -953,6 +960,9 @@ class Dumper(DumperBase): launchInfo = lldb.SBLaunchInfo(self.processArgs_) #launchInfo.SetWorkingDirectory(self.workingDirectory_) launchInfo.SetWorkingDirectory('/tmp') + if self.platform_ == 'remote-android': + launchInfo.SetWorkingDirectory('/data/local/tmp') + launchInfo.SetEnvironmentEntries(self.environment_, False) launchInfo.SetExecutableFile(f, True) DumperBase.warn("TARGET: %s" % self.target) diff --git a/src/plugins/android/androiddebugsupport.cpp b/src/plugins/android/androiddebugsupport.cpp index e20e55bd8ed..27a63173ebd 100644 --- a/src/plugins/android/androiddebugsupport.cpp +++ b/src/plugins/android/androiddebugsupport.cpp @@ -105,6 +105,7 @@ AndroidDebugSupport::AndroidDebugSupport(RunControl *runControl, const QString & : Debugger::DebuggerRunTool(runControl) { setId("AndroidDebugger"); + setLldbPlatform("remote-android"); m_runner = new AndroidRunner(runControl, intentName); addStartDependency(m_runner); } diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 4ef738996e3..34e0ee01e4d 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -307,7 +307,7 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, QString *stdOut, return result.success(); } -bool AndroidRunnerWorker::uploadDebugServer() +bool AndroidRunnerWorker::uploadDebugServer(const QString &debugServerFileName) { // Push the gdbserver or lldb-server to temp location and then to package dir. // the files can't be pushed directly to package because of permissions. @@ -322,7 +322,7 @@ bool AndroidRunnerWorker::uploadDebugServer() std::unique_ptr tempGdbServerPath(new QString("/data/local/tmp/%1"), cleanUp); - // Get a unique temp file name for gdbserver copy + // Get a unique temp file name for gdb/lldbserver copy int count = 0; while (deviceFileExists(tempGdbServerPath->arg(++count))) { if (count > GdbTempFileMaxCounter) { @@ -340,11 +340,11 @@ bool AndroidRunnerWorker::uploadDebugServer() } // Copy gdbserver from temp location to app directory - if (!runAdb({"shell", "run-as", m_packageName, "cp" , *tempGdbServerPath, "./gdbserver"})) { + if (!runAdb({"shell", "run-as", m_packageName, "cp" , *tempGdbServerPath, debugServerFileName})) { qCDebug(androidRunWorkerLog) << "Gdbserver copy from temp directory failed"; return false; } - QTC_ASSERT(runAdb({"shell", "run-as", m_packageName, "chmod", "777", "./gdbserver"}), + QTC_ASSERT(runAdb({"shell", "run-as", m_packageName, "chmod", "777", debugServerFileName}), qCDebug(androidRunWorkerLog) << "Gdbserver chmod 777 failed."); return true; } @@ -500,32 +500,38 @@ void AndroidRunnerWorker::asyncStartHelper() // e.g. on Android 8 with NDK 10e runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir.trimmed()}); - QString debugServerExecutable = "gdbserver"; - QString debugServerPrefix = "./lib/"; - auto findGdbServer = [this, &debugServerExecutable, debugServerPrefix](const QString& gdbEx) { - if (!packageFileExists(debugServerPrefix + gdbEx)) - return false; - debugServerExecutable = gdbEx; - return true; - }; - - if (!findGdbServer("gdbserver") && !findGdbServer("libgdbserver.so")) { - // Armv8. symlink lib is not available. - // Kill the previous instances of gdbserver. Do this before copying the gdbserver. - runAdb({"shell", "run-as", m_packageName, "killall", debugServerExecutable}); - if (!m_debugServerPath.isEmpty() && uploadDebugServer()) { - debugServerPrefix = "./"; - } else { - emit remoteProcessFinished(tr("Cannot find or copy C++ debug server.")); - return; - } + QString debugServerFile; + if (m_useLldb) { + debugServerFile = "./lldb-server"; + uploadDebugServer(debugServerFile); } else { - qCDebug(androidRunWorkerLog) << "Found GDB server under ./lib"; - runAdb({"shell", "run-as", m_packageName, "killall", debugServerExecutable}); - } + QString debugServerExecutable = "gdbserver"; + QString debugServerPrefix = "./lib/"; + auto findGdbServer = [this, &debugServerExecutable, debugServerPrefix](const QString& gdbEx) { + if (!packageFileExists(debugServerPrefix + gdbEx)) + return false; + debugServerExecutable = gdbEx; + return true; + }; + if (!findGdbServer("gdbserver") && !findGdbServer("libgdbserver.so")) { + // Armv8. symlink lib is not available. + // Kill the previous instances of gdbserver. Do this before copying the gdbserver. + runAdb({"shell", "run-as", m_packageName, "killall", debugServerExecutable}); + if (!m_debugServerPath.isEmpty() && uploadDebugServer("./gdbserver")) { + debugServerPrefix = "./"; + } else { + emit remoteProcessFinished(tr("Cannot find or copy C++ debug server.")); + return; + } + } else { + qCDebug(androidRunWorkerLog) << "Found GDB server under ./lib"; + runAdb({"shell", "run-as", m_packageName, "killall", debugServerExecutable}); + } + debugServerFile = debugServerPrefix + debugServerExecutable; + } QString debuggerServerErr; - if (!startDebuggerServer(packageDir, debugServerPrefix, debugServerExecutable, &debuggerServerErr)) { + if (!startDebuggerServer(packageDir, debugServerFile, &debuggerServerErr)) { emit remoteProcessFinished(debuggerServerErr); return; } @@ -578,37 +584,56 @@ void AndroidRunnerWorker::asyncStartHelper() } bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir, - const QString &debugServerPrefix, - const QString &debugServerExecutable, + const QString &debugServerFile, QString *errorStr) { - QString gdbServerSocket = packageDir + "/debug-socket"; - runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); + if (m_useLldb) { + QString lldbServerErr; + QStringList lldbServerArgs = selector(); + lldbServerArgs << "shell" << "run-as" << m_packageName << debugServerFile + << "platform" + << "--server" + << "--listen" << QString("*:%1").arg(m_localDebugServerPort.toString()); + m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(lldbServerArgs, &lldbServerErr)); - QString gdbProcessErr; - QStringList gdbServerArgs = selector(); - gdbServerArgs << "shell" << "run-as" << m_packageName << debugServerPrefix + debugServerExecutable - << "--multi" << "+" + gdbServerSocket; - m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(gdbServerArgs, &gdbProcessErr)); + if (!m_debugServerProcess) { + qCDebug(androidRunWorkerLog) << "Debugger process failed to start" << lldbServerErr; + if (errorStr) + *errorStr = tr("Failed to start debugger server."); + return false; + } + qCDebug(androidRunWorkerLog) << "Debugger process started"; + m_debugServerProcess->setObjectName("AndroidDebugServerProcess"); - if (!m_debugServerProcess) { - qCDebug(androidRunWorkerLog) << "Debugger process failed to start" << gdbProcessErr; - if (errorStr) - *errorStr = tr("Failed to start debugger server."); - return false; + } else { + QString gdbServerSocket = packageDir + "/debug-socket"; + runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); + + QString gdbProcessErr; + QStringList gdbServerErr = selector(); + gdbServerErr << "shell" << "run-as" << m_packageName << debugServerFile + << "--multi" << "+" + gdbServerSocket; + m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(gdbServerErr, &gdbProcessErr)); + + if (!m_debugServerProcess) { + qCDebug(androidRunWorkerLog) << "Debugger process failed to start" << gdbServerErr; + if (errorStr) + *errorStr = tr("Failed to start debugger server."); + return false; + } + qCDebug(androidRunWorkerLog) << "Debugger process started"; + m_debugServerProcess->setObjectName("AndroidDebugServerProcess"); + + QStringList removeForward{"forward", "--remove", "tcp:" + m_localDebugServerPort.toString()}; + runAdb(removeForward); + if (!runAdb({"forward", "tcp:" + m_localDebugServerPort.toString(), + "localfilesystem:" + gdbServerSocket})) { + if (errorStr) + *errorStr = tr("Failed to forward C++ debugging ports."); + return false; + } + m_afterFinishAdbCommands.push_back(removeForward.join(' ')); } - qCDebug(androidRunWorkerLog) << "Debugger process started"; - m_debugServerProcess->setObjectName("AndroidDebugServerProcess"); - - QStringList removeForward{"forward", "--remove", "tcp:" + m_localDebugServerPort.toString()}; - runAdb(removeForward); - if (!runAdb({"forward", "tcp:" + m_localDebugServerPort.toString(), - "localfilesystem:" + gdbServerSocket})) { - if (errorStr) - *errorStr = tr("Failed to forward C++ debugging ports."); - return false; - } - m_afterFinishAdbCommands.push_back(removeForward.join(' ')); return true; } @@ -665,7 +690,7 @@ void AndroidRunnerWorker::handleJdbWaiting() void AndroidRunnerWorker::handleJdbSettled() { qCDebug(androidRunWorkerLog) << "Handle JDB settled"; - auto waitForCommand = [&]() { + auto waitForCommand = [this]() { for (int i= 0; i < 5 && m_jdbProcess->state() == QProcess::Running; ++i) { m_jdbProcess->waitForReadyRead(500); QByteArray lines = m_jdbProcess->readAll(); @@ -708,7 +733,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid) if (pid == -1) { emit remoteProcessFinished(QLatin1String("\n\n") + tr("\"%1\" died.") .arg(m_packageName)); - // App died/killed. Reset log, monitor, jdb & gdb processes. + // App died/killed. Reset log, monitor, jdb & gdbserver/lldb-server processes. m_adbLogcatProcess.reset(); m_psIsAlive.reset(); m_jdbProcess.reset(); diff --git a/src/plugins/android/androidrunnerworker.h b/src/plugins/android/androidrunnerworker.h index d9b29a80043..f889e9e90d6 100644 --- a/src/plugins/android/androidrunnerworker.h +++ b/src/plugins/android/androidrunnerworker.h @@ -72,11 +72,10 @@ signals: private: void asyncStartHelper(); - bool startDebuggerServer(const QString &packageDir, const QString &gdbServerPrefix, - const QString &debugServerExecutable, QString *errorStr = nullptr); + bool startDebuggerServer(const QString &packageDir, const QString &debugServerFile, QString *errorStr = nullptr); bool deviceFileExists(const QString &filePath); bool packageFileExists(const QString& filePath); - bool uploadDebugServer(); + bool uploadDebugServer(const QString &debugServerFileName); enum class JDBState { Idle,