diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/android/androidrunnerworker.cpp | 90 | ||||
-rw-r--r-- | src/plugins/android/androidrunnerworker.h | 6 |
2 files changed, 71 insertions, 25 deletions
diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index a4b6772f61..37191848fd 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -53,6 +53,7 @@ namespace { Q_LOGGING_CATEGORY(androidRunWorkerLog, "qtc.android.run.androidrunnerworker", QtWarningMsg) +static const int GdbTempFileMaxCounter = 20; } using namespace std; @@ -274,17 +275,58 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS, const QB return success; } -bool AndroidRunnerWorker::uploadFile(const QString &from, const QString &to, const QString &flags) +bool AndroidRunnerWorker::uploadGdbServer() { - QFile f(from); - if (!f.open(QIODevice::ReadOnly)) + // Push the gdbserver to temp location and then to package dir. + // the files can't be pushed directly to package because of permissions. + qCDebug(androidRunWorkerLog) << "Uploading GdbServer"; + + bool foundUnique = true; + auto cleanUp = [this, &foundUnique] (QString *p) { + if (foundUnique && !runAdb({"shell", "rm", "-f", *p})) + qCDebug(androidRunWorkerLog) << "Gdbserver cleanup failed."; + delete p; + }; + std::unique_ptr<QString, decltype (cleanUp)> + tempGdbServerPath(new QString("/data/local/tmp/%1"), cleanUp); + + // Get a unique temp file name for gdbserver copy + int count = 0; + while (deviceFileExists(tempGdbServerPath->arg(++count))) { + if (count > GdbTempFileMaxCounter) { + qCDebug(androidRunWorkerLog) << "Can not get temporary file name"; + foundUnique = false; + return false; + } + } + *tempGdbServerPath = tempGdbServerPath->arg(count); + + // Copy gdbserver to temp location + if (!runAdb({"push", m_gdbserverPath , *tempGdbServerPath})) { + qCDebug(androidRunWorkerLog) << "Gdbserver upload to temp directory failed"; return false; - runAdb({"shell", "run-as", m_packageName, "rm", to}); - const QByteArray data = f.readAll(); - const bool res = runAdb({"shell", "run-as", m_packageName, QString("sh -c 'base64 -d > %1'").arg(to)}, 60, data.toBase64()); - if (!res || m_lastRunAdbRawOutput.contains("base64: not found")) + } + + // Copy gdbserver from temp location to app directory + if (!runAdb({"shell", "run-as", m_packageName, "cp" , *tempGdbServerPath, "./gdbserver"})) { + qCDebug(androidRunWorkerLog) << "Gdbserver copy from temp directory failed"; return false; - return runAdb({"shell", "run-as", m_packageName, "chmod", flags, to}); + } + QTC_ASSERT(runAdb({"shell", "run-as", m_packageName, "chmod", "+x", "./gdbserver"}), + qCDebug(androidRunWorkerLog) << "Gdbserver chmod +x failed."); + return true; +} + +bool AndroidRunnerWorker::deviceFileExists(const QString &filePath) +{ + return runAdb({"shell", "ls", filePath, "2>/dev/null"}) + && !m_lastRunAdbRawOutput.trimmed().isEmpty(); +} + +bool AndroidRunnerWorker::packageFileExists(const QString &filePath) +{ + return runAdb({"shell", "run-as", m_packageName, "ls", filePath, "2>/dev/null"}) + && !m_lastRunAdbRawOutput.trimmed().isEmpty(); } void AndroidRunnerWorker::adbKill(qint64 pid) @@ -428,29 +470,31 @@ void AndroidRunnerWorker::asyncStartHelper() // e.g. on Android 8 with NDK 10e runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir}); - QString gdbServerExecutable; + QString gdbServerExecutable = "gdbserver"; QString gdbServerPrefix = "./lib/"; - if (m_gdbserverPath.isEmpty() || !uploadFile(m_gdbserverPath, "gdbserver")) { - // upload failed - check for old devices - if (runAdb({"shell", "run-as", m_packageName, "ls", "lib/"})) { - for (const auto &line: m_lastRunAdbRawOutput.split('\n')) { - if (line.indexOf("gdbserver") != -1/* || line.indexOf("lldb-server") != -1*/) { - gdbServerExecutable = QString::fromUtf8(line.trimmed()); - break; - } - } - } - if (gdbServerExecutable.isEmpty()) { + auto findGdbServer = [this, &gdbServerExecutable, gdbServerPrefix](const QString& gdbEx) { + if (!packageFileExists(gdbServerPrefix + gdbEx)) + return false; + gdbServerExecutable = 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", gdbServerExecutable}); + if (!m_gdbserverPath.isEmpty() && uploadGdbServer()) { + gdbServerPrefix = "./"; + } else { emit remoteProcessFinished(tr("Cannot find/copy C++ debug server.")); return; } } else { - gdbServerPrefix = "./"; - gdbServerExecutable = "gdbserver"; + qCDebug(androidRunWorkerLog) << "Found GDB server under ./lib"; + runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); } QString gdbServerSocket = packageDir + "/debug-socket"; - runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter); diff --git a/src/plugins/android/androidrunnerworker.h b/src/plugins/android/androidrunnerworker.h index 18639683ae..39b25a1a29 100644 --- a/src/plugins/android/androidrunnerworker.h +++ b/src/plugins/android/androidrunnerworker.h @@ -48,7 +48,6 @@ public: ~AndroidRunnerWorker() override; bool adbShellAmNeedsQuotes(); bool runAdb(const QStringList &args, int timeoutS = 10, const QByteArray &writeData = {}); - bool uploadFile(const QString &from, const QString &to, const QString &flags = QString("+x")); void adbKill(qint64 pid); QStringList selector() const; void forceStop(); @@ -71,8 +70,11 @@ signals: void remoteOutput(const QString &output); void remoteErrorOutput(const QString &output); -protected: +private: void asyncStartHelper(); + bool deviceFileExists(const QString &filePath); + bool packageFileExists(const QString& filePath); + bool uploadGdbServer(); enum class JDBState { Idle, |