Index: lldb/trunk/source/Plugins/Platform/Android/AdbClient.h =================================================================== --- lldb/trunk/source/Plugins/Platform/Android/AdbClient.h +++ lldb/trunk/source/Plugins/Platform/Android/AdbClient.h @@ -62,6 +62,9 @@ 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 (); @@ -85,6 +88,9 @@ ReadMessage (std::vector &message); Error + ReadMessageStream (std::vector &message, uint32_t timeout_ms); + + Error GetResponseError (const char *response_id); Error Index: lldb/trunk/source/Plugins/Platform/Android/AdbClient.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/Android/AdbClient.cpp +++ lldb/trunk/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" @@ -212,6 +213,29 @@ } 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() { char response_id[5]; @@ -493,3 +517,30 @@ 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; +} Index: lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp =================================================================== --- lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ lldb/trunk/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -325,33 +325,21 @@ 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 @@ 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