From 9d8dde8ce57fd89ad5eb09a1bfbeda162e199141 Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Tue, 29 Sep 2015 11:04:18 +0000 Subject: [PATCH] Change oat symbolization code for android to work on non-rooted devices On android when debugging an apk we run lldb-server as application user because the sell user (on non-rooted device) can't attach to an application. The problem is that "adb pull" will run as a shell user what can't access to files created by lldb-server because they will be owned by the application user. This CL changes the oat symbolization code to run "oatdump --symbolize" to generate an output what is owned by the shell user. Differential revision: http://reviews.llvm.org/D13162 llvm-svn: 248788 --- .../Plugins/Platform/Android/AdbClient.cpp | 51 +++++++++++++++++++ .../Plugins/Platform/Android/AdbClient.h | 6 +++ .../Platform/Android/PlatformAndroid.cpp | 35 ++++--------- 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp index 11d4978c36b1..17fccb389373 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.cpp +++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp @@ -12,6 +12,7 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataEncoder.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -211,6 +212,29 @@ AdbClient::ReadMessage (std::vector &message) return error; } +Error +AdbClient::ReadMessageStream (std::vector& message, uint32_t timeout_ms) +{ + auto start = std::chrono::steady_clock::now(); + message.clear(); + + Error error; + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char buffer[1024]; + while (error.Success() && status == lldb::eConnectionStatusSuccess) + { + auto end = std::chrono::steady_clock::now(); + uint32_t elapsed_time = std::chrono::duration_cast(end - start).count(); + if (elapsed_time >= timeout_ms) + return Error("Timed out"); + + size_t n = m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error); + if (n > 0) + message.insert(message.end(), &buffer[0], &buffer[n]); + } + return error; +} + Error AdbClient::ReadResponseStatus() { @@ -493,3 +517,30 @@ AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, ui mtime = extractor.GetU32 (&offset); return Error (); } + +Error +AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output) +{ + auto error = SwitchDeviceTransport (); + if (error.Fail ()) + return Error ("Failed to switch to device transport: %s", error.AsCString ()); + + StreamString adb_command; + adb_command.Printf("shell:%s", command); + error = SendMessage (adb_command.GetData(), false); + if (error.Fail ()) + return error; + + error = ReadResponseStatus (); + if (error.Fail ()) + return error; + + std::vector in_buffer; + error = ReadMessageStream (in_buffer, timeout_ms); + if (error.Fail()) + return error; + + if (output) + output->assign(in_buffer.begin(), in_buffer.end()); + return error; +} diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.h b/lldb/source/Plugins/Platform/Android/AdbClient.h index bf76cfb4df52..25a72640c6ca 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.h +++ b/lldb/source/Plugins/Platform/Android/AdbClient.h @@ -62,6 +62,9 @@ public: Error Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + Error + Shell (const char* command, uint32_t timeout_ms, std::string* output); + private: Error Connect (); @@ -84,6 +87,9 @@ private: Error ReadMessage (std::vector &message); + Error + ReadMessageStream (std::vector &message, uint32_t timeout_ms); + Error GetResponseError (const char *response_id); diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp index 3d2546a18492..0d33c2b1290e 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -325,33 +325,21 @@ PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp, if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr) return Error("Symtab already available in the module"); - int status = 0; - std::string tmpdir; - StreamString command; - command.Printf("mktemp --directory --tmpdir %s", GetWorkingDirectory().GetCString()); - Error error = RunShellCommand(command.GetData(), - GetWorkingDirectory(), - &status, - nullptr, - &tmpdir, - 5 /* timeout (s) */); + AdbClient adb(m_device_id); - if (error.Fail() || status != 0 || tmpdir.empty()) + std::string tmpdir; + Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", 5000 /* ms */, &tmpdir); + if (error.Fail() || tmpdir.empty()) return Error("Failed to generate temporary directory on the device (%s)", error.AsCString()); tmpdir.erase(tmpdir.size() - 1); // Remove trailing new line // Create file remover for the temporary directory created on the device std::unique_ptr> tmpdir_remover( &tmpdir, - [this](std::string* s) { + [this, &adb](std::string* s) { StreamString command; command.Printf("rm -rf %s", s->c_str()); - Error error = this->RunShellCommand(command.GetData(), - GetWorkingDirectory(), - nullptr, - nullptr, - nullptr, - 5 /* timeout (s) */); + Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr); Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); if (error.Fail()) @@ -363,17 +351,12 @@ PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp, symfile_platform_filespec.AppendPathComponent("symbolized.oat"); // Execute oatdump on the remote device to generate a file with symtab - command.Clear(); + StreamString command; command.Printf("oatdump --symbolize=%s --output=%s", module_sp->GetPlatformFileSpec().GetCString(false), symfile_platform_filespec.GetCString(false)); - error = RunShellCommand(command.GetData(), - GetWorkingDirectory(), - &status, - nullptr, - nullptr, - 60 /* timeout (s) */); - if (error.Fail() || status != 0) + error = adb.Shell(command.GetData(), 60000 /* ms */, nullptr); + if (error.Fail()) return Error("Oatdump failed: %s", error.AsCString()); // Download the symbolfile from the remote device