Android: Fix gdbserver upload for Windows when using Armv8 arch

The gdbserver is not uploaded to device for armv7 as lib symlink
is available and we can use the gdbserver packaged with the apk

Task-number: QTCREATORBUG-21317
Change-Id: I263eb48bbf3cf05b969db934a928185dba10373b
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Vikas Pachdha
2018-12-20 18:40:34 +01:00
parent d886285ff0
commit 59de3fcb64
2 changed files with 71 additions and 25 deletions

View File

@@ -53,6 +53,7 @@
namespace { namespace {
Q_LOGGING_CATEGORY(androidRunWorkerLog, "qtc.android.run.androidrunnerworker", QtWarningMsg) Q_LOGGING_CATEGORY(androidRunWorkerLog, "qtc.android.run.androidrunnerworker", QtWarningMsg)
static const int GdbTempFileMaxCounter = 20;
} }
using namespace std; using namespace std;
@@ -274,17 +275,58 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, int timeoutS, const QB
return success; return success;
} }
bool AndroidRunnerWorker::uploadFile(const QString &from, const QString &to, const QString &flags) bool AndroidRunnerWorker::uploadGdbServer()
{ {
QFile f(from); // Push the gdbserver to temp location and then to package dir.
if (!f.open(QIODevice::ReadOnly)) // 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; 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()); // Copy gdbserver from temp location to app directory
if (!res || m_lastRunAdbRawOutput.contains("base64: not found")) if (!runAdb({"shell", "run-as", m_packageName, "cp" , *tempGdbServerPath, "./gdbserver"})) {
qCDebug(androidRunWorkerLog) << "Gdbserver copy from temp directory failed";
return false; 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) void AndroidRunnerWorker::adbKill(qint64 pid)
@@ -428,29 +470,31 @@ void AndroidRunnerWorker::asyncStartHelper()
// e.g. on Android 8 with NDK 10e // e.g. on Android 8 with NDK 10e
runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir}); runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir});
QString gdbServerExecutable; QString gdbServerExecutable = "gdbserver";
QString gdbServerPrefix = "./lib/"; QString gdbServerPrefix = "./lib/";
if (m_gdbserverPath.isEmpty() || !uploadFile(m_gdbserverPath, "gdbserver")) { auto findGdbServer = [this, &gdbServerExecutable, gdbServerPrefix](const QString& gdbEx) {
// upload failed - check for old devices if (!packageFileExists(gdbServerPrefix + gdbEx))
if (runAdb({"shell", "run-as", m_packageName, "ls", "lib/"})) { return false;
for (const auto &line: m_lastRunAdbRawOutput.split('\n')) { gdbServerExecutable = gdbEx;
if (line.indexOf("gdbserver") != -1/* || line.indexOf("lldb-server") != -1*/) { return true;
gdbServerExecutable = QString::fromUtf8(line.trimmed()); };
break;
} if (!findGdbServer("gdbserver") && !findGdbServer("libgdbserver.so")) {
} // Armv8. symlink lib is not available.
} // Kill the previous instances of gdbserver. Do this before copying the gdbserver.
if (gdbServerExecutable.isEmpty()) { runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable});
if (!m_gdbserverPath.isEmpty() && uploadGdbServer()) {
gdbServerPrefix = "./";
} else {
emit remoteProcessFinished(tr("Cannot find/copy C++ debug server.")); emit remoteProcessFinished(tr("Cannot find/copy C++ debug server."));
return; return;
} }
} else { } else {
gdbServerPrefix = "./"; qCDebug(androidRunWorkerLog) << "Found GDB server under ./lib";
gdbServerExecutable = "gdbserver"; runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable});
} }
QString gdbServerSocket = packageDir + "/debug-socket"; QString gdbServerSocket = packageDir + "/debug-socket";
runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable});
runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket});
std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter); std::unique_ptr<QProcess, Deleter> gdbServerProcess(new QProcess, deleter);

View File

@@ -48,7 +48,6 @@ public:
~AndroidRunnerWorker() override; ~AndroidRunnerWorker() override;
bool adbShellAmNeedsQuotes(); bool adbShellAmNeedsQuotes();
bool runAdb(const QStringList &args, int timeoutS = 10, const QByteArray &writeData = {}); 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); void adbKill(qint64 pid);
QStringList selector() const; QStringList selector() const;
void forceStop(); void forceStop();
@@ -71,8 +70,11 @@ signals:
void remoteOutput(const QString &output); void remoteOutput(const QString &output);
void remoteErrorOutput(const QString &output); void remoteErrorOutput(const QString &output);
protected: private:
void asyncStartHelper(); void asyncStartHelper();
bool deviceFileExists(const QString &filePath);
bool packageFileExists(const QString& filePath);
bool uploadGdbServer();
enum class JDBState { enum class JDBState {
Idle, Idle,