diff options
Diffstat (limited to 'lldb/source/Plugins/Platform/Android')
6 files changed, 1064 insertions, 1264 deletions
diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp index 05008169a5b..d7492285c97 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.cpp +++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp @@ -10,9 +10,9 @@ // Other libraries and framework includes #include "AdbClient.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/FileUtilities.h" #include "lldb/Core/DataBuffer.h" @@ -44,663 +44,602 @@ using namespace lldb_private::platform_android; namespace { const std::chrono::seconds kReadTimeout(8); -const char * kOKAY = "OKAY"; -const char * kFAIL = "FAIL"; -const char * kDATA = "DATA"; -const char * kDONE = "DONE"; +const char *kOKAY = "OKAY"; +const char *kFAIL = "FAIL"; +const char *kDATA = "DATA"; +const char *kDONE = "DONE"; -const char * kSEND = "SEND"; -const char * kRECV = "RECV"; -const char * kSTAT = "STAT"; +const char *kSEND = "SEND"; +const char *kRECV = "RECV"; +const char *kSTAT = "STAT"; const size_t kSyncPacketLen = 8; // Maximum size of a filesync DATA packet. -const size_t kMaxPushData = 2*1024; +const size_t kMaxPushData = 2 * 1024; // Default mode for pushed files. const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG -const char * kSocketNamespaceAbstract = "localabstract"; -const char * kSocketNamespaceFileSystem = "localfilesystem"; - -Error -ReadAllBytes (Connection &conn, void *buffer, size_t size) -{ - using namespace std::chrono; - - Error error; - ConnectionStatus status; - char *read_buffer = static_cast<char*>(buffer); - - auto now = steady_clock::now(); - const auto deadline = now + kReadTimeout; - size_t total_read_bytes = 0; - while (total_read_bytes < size && now < deadline) - { - uint32_t timeout_usec = duration_cast<microseconds>(deadline - now).count(); - auto read_bytes = - conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, timeout_usec, status, &error); - if (error.Fail ()) - return error; - total_read_bytes += read_bytes; - if (status != eConnectionStatusSuccess) - break; - now = steady_clock::now(); - } - if (total_read_bytes < size) - error = Error("Unable to read requested number of bytes. Connection status: %d.", status); - return error; -} +const char *kSocketNamespaceAbstract = "localabstract"; +const char *kSocketNamespaceFileSystem = "localfilesystem"; + +Error ReadAllBytes(Connection &conn, void *buffer, size_t size) { + using namespace std::chrono; -} // namespace + Error error; + ConnectionStatus status; + char *read_buffer = static_cast<char *>(buffer); -Error -AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb) -{ - DeviceIDList connect_devices; - auto error = adb.GetDevices(connect_devices); + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) { + uint32_t timeout_usec = duration_cast<microseconds>(deadline - now).count(); + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, + timeout_usec, status, &error); if (error.Fail()) - return error; - - std::string android_serial; - if (!device_id.empty()) - android_serial = device_id; - else if (const char *env_serial = std::getenv("ANDROID_SERIAL")) - android_serial = env_serial; - - if (android_serial.empty()) - { - if (connect_devices.size() != 1) - return Error("Expected a single connected device, got instead %zu - try setting 'ANDROID_SERIAL'", - connect_devices.size()); - adb.SetDeviceID(connect_devices.front()); - } - else - { - auto find_it = std::find(connect_devices.begin(), connect_devices.end(), android_serial); - if (find_it == connect_devices.end()) - return Error("Device \"%s\" not found", android_serial.c_str()); - - adb.SetDeviceID(*find_it); - } + return error; + total_read_bytes += read_bytes; + if (status != eConnectionStatusSuccess) + break; + now = steady_clock::now(); + } + if (total_read_bytes < size) + error = Error( + "Unable to read requested number of bytes. Connection status: %d.", + status); + return error; +} + +} // namespace + +Error AdbClient::CreateByDeviceID(const std::string &device_id, + AdbClient &adb) { + DeviceIDList connect_devices; + auto error = adb.GetDevices(connect_devices); + if (error.Fail()) return error; -} -AdbClient::AdbClient () {} + std::string android_serial; + if (!device_id.empty()) + android_serial = device_id; + else if (const char *env_serial = std::getenv("ANDROID_SERIAL")) + android_serial = env_serial; + + if (android_serial.empty()) { + if (connect_devices.size() != 1) + return Error("Expected a single connected device, got instead %zu - try " + "setting 'ANDROID_SERIAL'", + connect_devices.size()); + adb.SetDeviceID(connect_devices.front()); + } else { + auto find_it = std::find(connect_devices.begin(), connect_devices.end(), + android_serial); + if (find_it == connect_devices.end()) + return Error("Device \"%s\" not found", android_serial.c_str()); -AdbClient::AdbClient (const std::string &device_id) - : m_device_id (device_id) -{ + adb.SetDeviceID(*find_it); + } + return error; } +AdbClient::AdbClient() {} + +AdbClient::AdbClient(const std::string &device_id) : m_device_id(device_id) {} + AdbClient::~AdbClient() {} -void -AdbClient::SetDeviceID (const std::string &device_id) -{ - m_device_id = device_id; +void AdbClient::SetDeviceID(const std::string &device_id) { + m_device_id = device_id; } -const std::string& -AdbClient::GetDeviceID() const -{ - return m_device_id; -} +const std::string &AdbClient::GetDeviceID() const { return m_device_id; } -Error -AdbClient::Connect () -{ - Error error; - m_conn.reset (new ConnectionFileDescriptor); - m_conn->Connect ("connect://localhost:5037", &error); +Error AdbClient::Connect() { + Error error; + m_conn.reset(new ConnectionFileDescriptor); + m_conn->Connect("connect://localhost:5037", &error); - return error; + return error; } -Error -AdbClient::GetDevices (DeviceIDList &device_list) -{ - device_list.clear (); +Error AdbClient::GetDevices(DeviceIDList &device_list) { + device_list.clear(); - auto error = SendMessage ("host:devices"); - if (error.Fail ()) - return error; + auto error = SendMessage("host:devices"); + if (error.Fail()) + return error; - error = ReadResponseStatus (); - if (error.Fail ()) - return error; + error = ReadResponseStatus(); + if (error.Fail()) + return error; - std::vector<char> in_buffer; - error = ReadMessage (in_buffer); + std::vector<char> in_buffer; + error = ReadMessage(in_buffer); - llvm::StringRef response (&in_buffer[0], in_buffer.size ()); - llvm::SmallVector<llvm::StringRef, 4> devices; - response.split (devices, "\n", -1, false); + llvm::StringRef response(&in_buffer[0], in_buffer.size()); + llvm::SmallVector<llvm::StringRef, 4> devices; + response.split(devices, "\n", -1, false); - for (const auto device: devices) - device_list.push_back (device.split ('\t').first); + for (const auto device : devices) + device_list.push_back(device.split('\t').first); - // Force disconnect since ADB closes connection after host:devices - // response is sent. - m_conn.reset (); - return error; + // Force disconnect since ADB closes connection after host:devices + // response is sent. + m_conn.reset(); + return error; } -Error -AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port) -{ - char message[48]; - snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port); +Error AdbClient::SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port) { + char message[48]; + snprintf(message, sizeof(message), "forward:tcp:%d;tcp:%d", local_port, + remote_port); - const auto error = SendDeviceMessage (message); - if (error.Fail ()) - return error; + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; - return ReadResponseStatus (); + return ReadResponseStatus(); } -Error -AdbClient::SetPortForwarding (const uint16_t local_port, - const char* remote_socket_name, - const UnixSocketNamespace socket_namespace) -{ - char message[PATH_MAX]; - const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ? - kSocketNamespaceAbstract : kSocketNamespaceFileSystem; - snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s", - local_port, - sock_namespace_str, - remote_socket_name); +Error AdbClient::SetPortForwarding(const uint16_t local_port, + const char *remote_socket_name, + const UnixSocketNamespace socket_namespace) { + char message[PATH_MAX]; + const char *sock_namespace_str = + (socket_namespace == UnixSocketNamespaceAbstract) + ? kSocketNamespaceAbstract + : kSocketNamespaceFileSystem; + snprintf(message, sizeof(message), "forward:tcp:%d;%s:%s", local_port, + sock_namespace_str, remote_socket_name); - const auto error = SendDeviceMessage (message); - if (error.Fail ()) - return error; + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; - return ReadResponseStatus (); + return ReadResponseStatus(); } -Error -AdbClient::DeletePortForwarding (const uint16_t local_port) -{ - char message[32]; - snprintf (message, sizeof (message), "killforward:tcp:%d", local_port); +Error AdbClient::DeletePortForwarding(const uint16_t local_port) { + char message[32]; + snprintf(message, sizeof(message), "killforward:tcp:%d", local_port); - const auto error = SendDeviceMessage (message); - if (error.Fail ()) - return error; + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; - return ReadResponseStatus (); + return ReadResponseStatus(); } -Error -AdbClient::SendMessage (const std::string &packet, const bool reconnect) -{ - Error error; - if (!m_conn || reconnect) - { - error = Connect (); - if (error.Fail ()) - return error; - } - - char length_buffer[5]; - snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ())); +Error AdbClient::SendMessage(const std::string &packet, const bool reconnect) { + Error error; + if (!m_conn || reconnect) { + error = Connect(); + if (error.Fail()) + return error; + } - ConnectionStatus status; + char length_buffer[5]; + snprintf(length_buffer, sizeof(length_buffer), "%04x", + static_cast<int>(packet.size())); - m_conn->Write (length_buffer, 4, status, &error); - if (error.Fail ()) - return error; + ConnectionStatus status; - m_conn->Write (packet.c_str (), packet.size (), status, &error); + m_conn->Write(length_buffer, 4, status, &error); + if (error.Fail()) return error; + + m_conn->Write(packet.c_str(), packet.size(), status, &error); + return error; } -Error -AdbClient::SendDeviceMessage (const std::string &packet) -{ - std::ostringstream msg; - msg << "host-serial:" << m_device_id << ":" << packet; - return SendMessage (msg.str ()); +Error AdbClient::SendDeviceMessage(const std::string &packet) { + std::ostringstream msg; + msg << "host-serial:" << m_device_id << ":" << packet; + return SendMessage(msg.str()); } -Error -AdbClient::ReadMessage (std::vector<char> &message) -{ - message.clear (); +Error AdbClient::ReadMessage(std::vector<char> &message) { + message.clear(); - char buffer[5]; - buffer[4] = 0; + char buffer[5]; + buffer[4] = 0; - auto error = ReadAllBytes (buffer, 4); - if (error.Fail ()) - return error; + auto error = ReadAllBytes(buffer, 4); + if (error.Fail()) + return error; - unsigned int packet_len = 0; - sscanf (buffer, "%x", &packet_len); + unsigned int packet_len = 0; + sscanf(buffer, "%x", &packet_len); - message.resize (packet_len, 0); - error = ReadAllBytes (&message[0], packet_len); - if (error.Fail ()) - message.clear (); + message.resize(packet_len, 0); + error = ReadAllBytes(&message[0], packet_len); + if (error.Fail()) + message.clear(); - return error; + return error; } -Error -AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms) -{ - auto start = std::chrono::steady_clock::now(); - message.clear(); +Error AdbClient::ReadMessageStream(std::vector<char> &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<std::chrono::milliseconds>(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 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<std::chrono::milliseconds>(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]; +Error AdbClient::ReadResponseStatus() { + char response_id[5]; - static const size_t packet_len = 4; - response_id[packet_len] = 0; + static const size_t packet_len = 4; + response_id[packet_len] = 0; - auto error = ReadAllBytes (response_id, packet_len); - if (error.Fail ()) - return error; + auto error = ReadAllBytes(response_id, packet_len); + if (error.Fail()) + return error; - if (strncmp (response_id, kOKAY, packet_len) != 0) - return GetResponseError (response_id); + if (strncmp(response_id, kOKAY, packet_len) != 0) + return GetResponseError(response_id); - return error; + return error; } -Error -AdbClient::GetResponseError (const char *response_id) -{ - if (strcmp (response_id, kFAIL) != 0) - return Error ("Got unexpected response id from adb: \"%s\"", response_id); +Error AdbClient::GetResponseError(const char *response_id) { + if (strcmp(response_id, kFAIL) != 0) + return Error("Got unexpected response id from adb: \"%s\"", response_id); - std::vector<char> error_message; - auto error = ReadMessage (error_message); - if (error.Success ()) - error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ()); + std::vector<char> error_message; + auto error = ReadMessage(error_message); + if (error.Success()) + error.SetErrorString( + std::string(&error_message[0], error_message.size()).c_str()); - return error; + return error; } -Error -AdbClient::SwitchDeviceTransport () -{ - std::ostringstream msg; - msg << "host:transport:" << m_device_id; +Error AdbClient::SwitchDeviceTransport() { + std::ostringstream msg; + msg << "host:transport:" << m_device_id; - auto error = SendMessage (msg.str ()); - if (error.Fail ()) - return error; + auto error = SendMessage(msg.str()); + if (error.Fail()) + return error; - return ReadResponseStatus (); + return ReadResponseStatus(); } -Error -AdbClient::StartSync () -{ - auto error = SwitchDeviceTransport (); - if (error.Fail ()) - return Error ("Failed to switch to device transport: %s", error.AsCString ()); +Error AdbClient::StartSync() { + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Error("Failed to switch to device transport: %s", error.AsCString()); - error = Sync (); - if (error.Fail ()) - return Error ("Sync failed: %s", error.AsCString ()); + error = Sync(); + if (error.Fail()) + return Error("Sync failed: %s", error.AsCString()); - return error; + return error; } -Error -AdbClient::Sync () -{ - auto error = SendMessage ("sync:", false); - if (error.Fail ()) - return error; +Error AdbClient::Sync() { + auto error = SendMessage("sync:", false); + if (error.Fail()) + return error; - return ReadResponseStatus (); + return ReadResponseStatus(); } -Error -AdbClient::ReadAllBytes (void *buffer, size_t size) -{ - return ::ReadAllBytes (*m_conn, buffer, size); +Error AdbClient::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); } -Error -AdbClient::internalShell(const char *command, uint32_t timeout_ms, std::vector<char> &output_buf) -{ - output_buf.clear(); +Error AdbClient::internalShell(const char *command, uint32_t timeout_ms, + std::vector<char> &output_buf) { + output_buf.clear(); - auto error = SwitchDeviceTransport(); - if (error.Fail()) - return Error("Failed to switch to device transport: %s", error.AsCString()); + 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; + 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; + error = ReadResponseStatus(); + if (error.Fail()) + return error; - error = ReadMessageStream(output_buf, timeout_ms); - if (error.Fail()) - return error; - - // ADB doesn't propagate return code of shell execution - if - // output starts with /system/bin/sh: most likely command failed. - static const char *kShellPrefix = "/system/bin/sh:"; - if (output_buf.size() > strlen(kShellPrefix)) - { - if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix))) - return Error("Shell command %s failed: %s", command, - std::string(output_buf.begin(), output_buf.end()).c_str()); - } - - return Error(); -} - -Error -AdbClient::Shell(const char *command, uint32_t timeout_ms, std::string *output) -{ - std::vector<char> output_buffer; - auto error = internalShell(command, timeout_ms, output_buffer); - if (error.Fail()) - return error; + error = ReadMessageStream(output_buf, timeout_ms); + if (error.Fail()) + return error; - if (output) - output->assign(output_buffer.begin(), output_buffer.end()); + // ADB doesn't propagate return code of shell execution - if + // output starts with /system/bin/sh: most likely command failed. + static const char *kShellPrefix = "/system/bin/sh:"; + if (output_buf.size() > strlen(kShellPrefix)) { + if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix))) + return Error("Shell command %s failed: %s", command, + std::string(output_buf.begin(), output_buf.end()).c_str()); + } + + return Error(); +} + +Error AdbClient::Shell(const char *command, uint32_t timeout_ms, + std::string *output) { + std::vector<char> output_buffer; + auto error = internalShell(command, timeout_ms, output_buffer); + if (error.Fail()) return error; + + if (output) + output->assign(output_buffer.begin(), output_buffer.end()); + return error; } -Error -AdbClient::ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec) -{ - std::vector<char> output_buffer; - auto error = internalShell(command, timeout_ms, output_buffer); - if (error.Fail()) - return error; +Error AdbClient::ShellToFile(const char *command, uint32_t timeout_ms, + const FileSpec &output_file_spec) { + std::vector<char> output_buffer; + auto error = internalShell(command, timeout_ms, output_buffer); + if (error.Fail()) + return error; - const auto output_filename = output_file_spec.GetPath(); - std::ofstream dst(output_filename, std::ios::out | std::ios::binary); - if (!dst.is_open()) - return Error("Unable to open local file %s", output_filename.c_str()); + const auto output_filename = output_file_spec.GetPath(); + std::ofstream dst(output_filename, std::ios::out | std::ios::binary); + if (!dst.is_open()) + return Error("Unable to open local file %s", output_filename.c_str()); - dst.write(&output_buffer[0], output_buffer.size()); - dst.close(); - if (!dst) - return Error("Failed to write file %s", output_filename.c_str()); - return Error(); + dst.write(&output_buffer[0], output_buffer.size()); + dst.close(); + if (!dst) + return Error("Failed to write file %s", output_filename.c_str()); + return Error(); } std::unique_ptr<AdbClient::SyncService> -AdbClient::GetSyncService (Error &error) -{ - std::unique_ptr<SyncService> sync_service; - error = StartSync (); - if (error.Success ()) - sync_service.reset (new SyncService(std::move(m_conn))); - - return sync_service; -} - -Error -AdbClient::SyncService::internalPullFile (const FileSpec &remote_file, const FileSpec &local_file) -{ - const auto local_file_path = local_file.GetPath (); - llvm::FileRemover local_file_remover (local_file_path.c_str ()); - - std::ofstream dst (local_file_path, std::ios::out | std::ios::binary); - if (!dst.is_open ()) - return Error ("Unable to open local file %s", local_file_path.c_str()); - - const auto remote_file_path = remote_file.GetPath (false); - auto error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ()); - if (error.Fail ()) - return error; - - std::vector<char> chunk; - bool eof = false; - while (!eof) - { - error = PullFileChunk (chunk, eof); - if (error.Fail ()) - return error; - if (!eof) - dst.write (&chunk[0], chunk.size ()); - } - - local_file_remover.releaseFile (); - return error; +AdbClient::GetSyncService(Error &error) { + std::unique_ptr<SyncService> sync_service; + error = StartSync(); + if (error.Success()) + sync_service.reset(new SyncService(std::move(m_conn))); + + return sync_service; } -Error -AdbClient::SyncService::internalPushFile (const FileSpec &local_file, const FileSpec &remote_file) -{ - const auto local_file_path (local_file.GetPath ()); - std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary); - if (!src.is_open ()) - return Error ("Unable to open local file %s", local_file_path.c_str()); - - std::stringstream file_description; - file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode; - std::string file_description_str = file_description.str(); - auto error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str()); - if (error.Fail ()) - return error; - - char chunk[kMaxPushData]; - while (!src.eof() && !src.read(chunk, kMaxPushData).bad()) - { - size_t chunk_size = src.gcount(); - error = SendSyncRequest(kDATA, chunk_size, chunk); - if (error.Fail ()) - return Error ("Failed to send file chunk: %s", error.AsCString ()); - } - error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr); - if (error.Fail ()) - return error; - - std::string response_id; - uint32_t data_len; - error = ReadSyncHeader (response_id, data_len); - if (error.Fail ()) - return Error ("Failed to read DONE response: %s", error.AsCString ()); - if (response_id == kFAIL) - { - std::string error_message (data_len, 0); - error = ReadAllBytes (&error_message[0], data_len); - if (error.Fail ()) - return Error ("Failed to read DONE error message: %s", error.AsCString ()); - return Error ("Failed to push file: %s", error_message.c_str ()); - } - else if (response_id != kOKAY) - return Error ("Got unexpected DONE response: %s", response_id.c_str ()); - - // If there was an error reading the source file, finish the adb file - // transfer first so that adb isn't expecting any more data. - if (src.bad()) - return Error ("Failed read on %s", local_file_path.c_str()); +Error AdbClient::SyncService::internalPullFile(const FileSpec &remote_file, + const FileSpec &local_file) { + const auto local_file_path = local_file.GetPath(); + llvm::FileRemover local_file_remover(local_file_path.c_str()); + + std::ofstream dst(local_file_path, std::ios::out | std::ios::binary); + if (!dst.is_open()) + return Error("Unable to open local file %s", local_file_path.c_str()); + + const auto remote_file_path = remote_file.GetPath(false); + auto error = SendSyncRequest(kRECV, remote_file_path.length(), + remote_file_path.c_str()); + if (error.Fail()) + return error; + + std::vector<char> chunk; + bool eof = false; + while (!eof) { + error = PullFileChunk(chunk, eof); + if (error.Fail()) + return error; + if (!eof) + dst.write(&chunk[0], chunk.size()); + } + + local_file_remover.releaseFile(); + return error; +} + +Error AdbClient::SyncService::internalPushFile(const FileSpec &local_file, + const FileSpec &remote_file) { + const auto local_file_path(local_file.GetPath()); + std::ifstream src(local_file_path.c_str(), std::ios::in | std::ios::binary); + if (!src.is_open()) + return Error("Unable to open local file %s", local_file_path.c_str()); + + std::stringstream file_description; + file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode; + std::string file_description_str = file_description.str(); + auto error = SendSyncRequest(kSEND, file_description_str.length(), + file_description_str.c_str()); + if (error.Fail()) + return error; + + char chunk[kMaxPushData]; + while (!src.eof() && !src.read(chunk, kMaxPushData).bad()) { + size_t chunk_size = src.gcount(); + error = SendSyncRequest(kDATA, chunk_size, chunk); + if (error.Fail()) + return Error("Failed to send file chunk: %s", error.AsCString()); + } + error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), + nullptr); + if (error.Fail()) return error; + + std::string response_id; + uint32_t data_len; + error = ReadSyncHeader(response_id, data_len); + if (error.Fail()) + return Error("Failed to read DONE response: %s", error.AsCString()); + if (response_id == kFAIL) { + std::string error_message(data_len, 0); + error = ReadAllBytes(&error_message[0], data_len); + if (error.Fail()) + return Error("Failed to read DONE error message: %s", error.AsCString()); + return Error("Failed to push file: %s", error_message.c_str()); + } else if (response_id != kOKAY) + return Error("Got unexpected DONE response: %s", response_id.c_str()); + + // If there was an error reading the source file, finish the adb file + // transfer first so that adb isn't expecting any more data. + if (src.bad()) + return Error("Failed read on %s", local_file_path.c_str()); + return error; } -Error -AdbClient::SyncService::internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) -{ - const std::string remote_file_path (remote_file.GetPath (false)); - auto error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ()); - if (error.Fail ()) - return Error ("Failed to send request: %s", error.AsCString ()); +Error AdbClient::SyncService::internalStat(const FileSpec &remote_file, + uint32_t &mode, uint32_t &size, + uint32_t &mtime) { + const std::string remote_file_path(remote_file.GetPath(false)); + auto error = SendSyncRequest(kSTAT, remote_file_path.length(), + remote_file_path.c_str()); + if (error.Fail()) + return Error("Failed to send request: %s", error.AsCString()); - static const size_t stat_len = strlen (kSTAT); - static const size_t response_len = stat_len + (sizeof (uint32_t) * 3); + static const size_t stat_len = strlen(kSTAT); + static const size_t response_len = stat_len + (sizeof(uint32_t) * 3); - std::vector<char> buffer (response_len); - error = ReadAllBytes (&buffer[0], buffer.size ()); - if (error.Fail ()) - return Error ("Failed to read response: %s", error.AsCString ()); + std::vector<char> buffer(response_len); + error = ReadAllBytes(&buffer[0], buffer.size()); + if (error.Fail()) + return Error("Failed to read response: %s", error.AsCString()); - DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*)); - offset_t offset = 0; + DataExtractor extractor(&buffer[0], buffer.size(), eByteOrderLittle, + sizeof(void *)); + offset_t offset = 0; - const void* command = extractor.GetData (&offset, stat_len); - if (!command) - return Error ("Failed to get response command"); - const char* command_str = static_cast<const char*> (command); - if (strncmp (command_str, kSTAT, stat_len)) - return Error ("Got invalid stat command: %s", command_str); + const void *command = extractor.GetData(&offset, stat_len); + if (!command) + return Error("Failed to get response command"); + const char *command_str = static_cast<const char *>(command); + if (strncmp(command_str, kSTAT, stat_len)) + return Error("Got invalid stat command: %s", command_str); - mode = extractor.GetU32 (&offset); - size = extractor.GetU32 (&offset); - mtime = extractor.GetU32 (&offset); - return Error (); + mode = extractor.GetU32(&offset); + size = extractor.GetU32(&offset); + mtime = extractor.GetU32(&offset); + return Error(); } -Error -AdbClient::SyncService::PullFile (const FileSpec &remote_file, const FileSpec &local_file) -{ - return executeCommand ([this, &remote_file, &local_file]() { - return internalPullFile (remote_file, local_file); - }); +Error AdbClient::SyncService::PullFile(const FileSpec &remote_file, + const FileSpec &local_file) { + return executeCommand([this, &remote_file, &local_file]() { + return internalPullFile(remote_file, local_file); + }); } -Error -AdbClient::SyncService::PushFile (const FileSpec &local_file, const FileSpec &remote_file) -{ - return executeCommand ([this, &local_file, &remote_file]() { - return internalPushFile (local_file, remote_file); - }); +Error AdbClient::SyncService::PushFile(const FileSpec &local_file, + const FileSpec &remote_file) { + return executeCommand([this, &local_file, &remote_file]() { + return internalPushFile(local_file, remote_file); + }); } -Error -AdbClient::SyncService::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) -{ - return executeCommand ([this, &remote_file, &mode, &size, &mtime]() { - return internalStat (remote_file, mode, size, mtime); - }); +Error AdbClient::SyncService::Stat(const FileSpec &remote_file, uint32_t &mode, + uint32_t &size, uint32_t &mtime) { + return executeCommand([this, &remote_file, &mode, &size, &mtime]() { + return internalStat(remote_file, mode, size, mtime); + }); } -bool -AdbClient::SyncService::IsConnected () const -{ - return m_conn && m_conn->IsConnected (); +bool AdbClient::SyncService::IsConnected() const { + return m_conn && m_conn->IsConnected(); } -AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn): -m_conn(std::move(conn)) -{ -} +AdbClient::SyncService::SyncService(std::unique_ptr<Connection> &&conn) + : m_conn(std::move(conn)) {} -Error -AdbClient::SyncService::executeCommand (const std::function<Error()> &cmd) -{ - if (!m_conn) - return Error ("SyncService is disconnected"); +Error AdbClient::SyncService::executeCommand( + const std::function<Error()> &cmd) { + if (!m_conn) + return Error("SyncService is disconnected"); - const auto error = cmd (); - if (error.Fail ()) - m_conn.reset (); + const auto error = cmd(); + if (error.Fail()) + m_conn.reset(); - return error; + return error; } -AdbClient::SyncService::~SyncService () {} +AdbClient::SyncService::~SyncService() {} -Error -AdbClient::SyncService::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data) -{ - const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0)); - DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*)); - auto offset = encoder.PutData (0, request_id, strlen(request_id)); - encoder.PutU32 (offset, data_len); +Error AdbClient::SyncService::SendSyncRequest(const char *request_id, + const uint32_t data_len, + const void *data) { + const DataBufferSP data_sp(new DataBufferHeap(kSyncPacketLen, 0)); + DataEncoder encoder(data_sp, eByteOrderLittle, sizeof(void *)); + auto offset = encoder.PutData(0, request_id, strlen(request_id)); + encoder.PutU32(offset, data_len); - Error error; - ConnectionStatus status; - m_conn->Write (data_sp->GetBytes (), kSyncPacketLen, status, &error); - if (error.Fail ()) - return error; - - if (data) - m_conn->Write (data, data_len, status, &error); + Error error; + ConnectionStatus status; + m_conn->Write(data_sp->GetBytes(), kSyncPacketLen, status, &error); + if (error.Fail()) return error; + + if (data) + m_conn->Write(data, data_len, status, &error); + return error; } -Error -AdbClient::SyncService::ReadSyncHeader (std::string &response_id, uint32_t &data_len) -{ - char buffer[kSyncPacketLen]; +Error AdbClient::SyncService::ReadSyncHeader(std::string &response_id, + uint32_t &data_len) { + char buffer[kSyncPacketLen]; - auto error = ReadAllBytes (buffer, kSyncPacketLen); - if (error.Success ()) - { - response_id.assign (&buffer[0], 4); - DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*)); - offset_t offset = 0; - data_len = extractor.GetU32 (&offset); - } + auto error = ReadAllBytes(buffer, kSyncPacketLen); + if (error.Success()) { + response_id.assign(&buffer[0], 4); + DataExtractor extractor(&buffer[4], 4, eByteOrderLittle, sizeof(void *)); + offset_t offset = 0; + data_len = extractor.GetU32(&offset); + } - return error; + return error; } -Error -AdbClient::SyncService::PullFileChunk (std::vector<char> &buffer, bool &eof) -{ - buffer.clear (); - - std::string response_id; - uint32_t data_len; - auto error = ReadSyncHeader (response_id, data_len); - if (error.Fail ()) - return error; - - if (response_id == kDATA) - { - buffer.resize (data_len, 0); - error = ReadAllBytes (&buffer[0], data_len); - if (error.Fail ()) - buffer.clear (); - } - else if (response_id == kDONE) - { - eof = true; - } - else if (response_id == kFAIL) - { - std::string error_message (data_len, 0); - error = ReadAllBytes (&error_message[0], data_len); - if (error.Fail ()) - return Error ("Failed to read pull error message: %s", error.AsCString ()); - return Error ("Failed to pull file: %s", error_message.c_str ()); - } - else - return Error ("Pull failed with unknown response: %s", response_id.c_str ()); - - return Error (); -} - -Error -AdbClient::SyncService::ReadAllBytes (void *buffer, size_t size) -{ - return ::ReadAllBytes (*m_conn, buffer, size); +Error AdbClient::SyncService::PullFileChunk(std::vector<char> &buffer, + bool &eof) { + buffer.clear(); + + std::string response_id; + uint32_t data_len; + auto error = ReadSyncHeader(response_id, data_len); + if (error.Fail()) + return error; + + if (response_id == kDATA) { + buffer.resize(data_len, 0); + error = ReadAllBytes(&buffer[0], data_len); + if (error.Fail()) + buffer.clear(); + } else if (response_id == kDONE) { + eof = true; + } else if (response_id == kFAIL) { + std::string error_message(data_len, 0); + error = ReadAllBytes(&error_message[0], data_len); + if (error.Fail()) + return Error("Failed to read pull error message: %s", error.AsCString()); + return Error("Failed to pull file: %s", error_message.c_str()); + } else + return Error("Pull failed with unknown response: %s", response_id.c_str()); + + return Error(); } +Error AdbClient::SyncService::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); +} diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.h b/lldb/source/Plugins/Platform/Android/AdbClient.h index 37973bbdccf..471dce5ea75 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.h +++ b/lldb/source/Plugins/Platform/Android/AdbClient.h @@ -31,146 +31,116 @@ class FileSpec; namespace platform_android { -class AdbClient -{ +class AdbClient { public: - enum UnixSocketNamespace - { - UnixSocketNamespaceAbstract, - UnixSocketNamespaceFileSystem, - }; + enum UnixSocketNamespace { + UnixSocketNamespaceAbstract, + UnixSocketNamespaceFileSystem, + }; - using DeviceIDList = std::list<std::string>; + using DeviceIDList = std::list<std::string>; - class SyncService - { - friend class AdbClient; + class SyncService { + friend class AdbClient; - public: - ~SyncService (); + public: + ~SyncService(); - Error - PullFile (const FileSpec &remote_file, const FileSpec &local_file); + Error PullFile(const FileSpec &remote_file, const FileSpec &local_file); - Error - PushFile (const FileSpec &local_file, const FileSpec &remote_file); + Error PushFile(const FileSpec &local_file, const FileSpec &remote_file); - Error - Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + Error Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size, + uint32_t &mtime); - bool - IsConnected () const; + bool IsConnected() const; - private: - explicit SyncService (std::unique_ptr<Connection> &&conn); + private: + explicit SyncService(std::unique_ptr<Connection> &&conn); - Error - SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data); + Error SendSyncRequest(const char *request_id, const uint32_t data_len, + const void *data); - Error - ReadSyncHeader (std::string &response_id, uint32_t &data_len); + Error ReadSyncHeader(std::string &response_id, uint32_t &data_len); - Error - PullFileChunk (std::vector<char> &buffer, bool &eof); + Error PullFileChunk(std::vector<char> &buffer, bool &eof); - Error - ReadAllBytes (void *buffer, size_t size); + Error ReadAllBytes(void *buffer, size_t size); - Error - internalPullFile (const FileSpec &remote_file, const FileSpec &local_file); + Error internalPullFile(const FileSpec &remote_file, + const FileSpec &local_file); - Error - internalPushFile (const FileSpec &local_file, const FileSpec &remote_file); + Error internalPushFile(const FileSpec &local_file, + const FileSpec &remote_file); - Error - internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + Error internalStat(const FileSpec &remote_file, uint32_t &mode, + uint32_t &size, uint32_t &mtime); - Error - executeCommand (const std::function<Error()> &cmd); + Error executeCommand(const std::function<Error()> &cmd); - std::unique_ptr<Connection> m_conn; - }; + std::unique_ptr<Connection> m_conn; + }; - static Error - CreateByDeviceID(const std::string &device_id, AdbClient &adb); + static Error CreateByDeviceID(const std::string &device_id, AdbClient &adb); - AdbClient (); - explicit AdbClient (const std::string &device_id); + AdbClient(); + explicit AdbClient(const std::string &device_id); - ~AdbClient(); + ~AdbClient(); - const std::string& - GetDeviceID() const; + const std::string &GetDeviceID() const; - Error - GetDevices (DeviceIDList &device_list); + Error GetDevices(DeviceIDList &device_list); - Error - SetPortForwarding (const uint16_t local_port, const uint16_t remote_port); + Error SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port); - Error - SetPortForwarding (const uint16_t local_port, - const char* remote_socket_name, - const UnixSocketNamespace socket_namespace); + Error SetPortForwarding(const uint16_t local_port, + const char *remote_socket_name, + const UnixSocketNamespace socket_namespace); - Error - DeletePortForwarding (const uint16_t local_port); + Error DeletePortForwarding(const uint16_t local_port); - Error - Shell (const char* command, uint32_t timeout_ms, std::string* output); + Error Shell(const char *command, uint32_t timeout_ms, std::string *output); - Error - ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec); + Error ShellToFile(const char *command, uint32_t timeout_ms, + const FileSpec &output_file_spec); - std::unique_ptr<SyncService> - GetSyncService (Error &error); + std::unique_ptr<SyncService> GetSyncService(Error &error); - Error - SwitchDeviceTransport (); + Error SwitchDeviceTransport(); private: - Error - Connect (); + Error Connect(); - void - SetDeviceID (const std::string &device_id); + void SetDeviceID(const std::string &device_id); - Error - SendMessage (const std::string &packet, const bool reconnect = true); + Error SendMessage(const std::string &packet, const bool reconnect = true); - Error - SendDeviceMessage (const std::string &packet); + Error SendDeviceMessage(const std::string &packet); - Error - ReadMessage (std::vector<char> &message); + Error ReadMessage(std::vector<char> &message); - Error - ReadMessageStream (std::vector<char> &message, uint32_t timeout_ms); + Error ReadMessageStream(std::vector<char> &message, uint32_t timeout_ms); - Error - GetResponseError (const char *response_id); + Error GetResponseError(const char *response_id); - Error - ReadResponseStatus (); + Error ReadResponseStatus(); - Error - Sync (); + Error Sync(); - Error - StartSync (); + Error StartSync(); - Error - internalShell(const char *command, uint32_t timeout_ms, std::vector<char> &output_buf); + Error internalShell(const char *command, uint32_t timeout_ms, + std::vector<char> &output_buf); - Error - ReadAllBytes(void *buffer, size_t size); + Error ReadAllBytes(void *buffer, size_t size); - std::string m_device_id; - std::unique_ptr<Connection> m_conn; + std::string m_device_id; + std::unique_ptr<Connection> m_conn; }; } // namespace platform_android } // namespace lldb_private -#endif // liblldb_AdbClient_h_ - +#endif // liblldb_AdbClient_h_ diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp index 52a9e763e17..364bd9106b4 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -10,6 +10,7 @@ // C Includes // C++ Includes // Other libraries and framework includes +#include "Utility/UriParser.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" @@ -18,7 +19,6 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" -#include "Utility/UriParser.h" // Project includes #include "AdbClient.h" @@ -30,388 +30,346 @@ using namespace lldb_private; using namespace lldb_private::platform_android; static uint32_t g_initialize_count = 0; -static const unsigned int g_android_default_cache_size = 2048; // Fits inside 4k adb packet. +static const unsigned int g_android_default_cache_size = + 2048; // Fits inside 4k adb packet. -void -PlatformAndroid::Initialize () -{ - PlatformLinux::Initialize (); +void PlatformAndroid::Initialize() { + PlatformLinux::Initialize(); - if (g_initialize_count++ == 0) - { + if (g_initialize_count++ == 0) { #if defined(__ANDROID__) - PlatformSP default_platform_sp (new PlatformAndroid(true)); - default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); - Platform::SetHostPlatform (default_platform_sp); + PlatformSP default_platform_sp(new PlatformAndroid(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); #endif - PluginManager::RegisterPlugin (PlatformAndroid::GetPluginNameStatic(false), - PlatformAndroid::GetPluginDescriptionStatic(false), - PlatformAndroid::CreateInstance); - } + PluginManager::RegisterPlugin( + PlatformAndroid::GetPluginNameStatic(false), + PlatformAndroid::GetPluginDescriptionStatic(false), + PlatformAndroid::CreateInstance); + } } -void -PlatformAndroid::Terminate () -{ - if (g_initialize_count > 0) - { - if (--g_initialize_count == 0) - { - PluginManager::UnregisterPlugin (PlatformAndroid::CreateInstance); - } +void PlatformAndroid::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance); } + } - PlatformLinux::Terminate (); + PlatformLinux::Terminate(); } -PlatformSP -PlatformAndroid::CreateInstance (bool force, const ArchSpec *arch) -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); - if (log) - { - const char *arch_name; - if (arch && arch->GetArchitectureName ()) - arch_name = arch->GetArchitectureName (); - else - arch_name = "<null>"; +PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + const char *arch_name; + if (arch && arch->GetArchitectureName()) + arch_name = arch->GetArchitectureName(); + else + arch_name = "<null>"; - const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>"; + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : "<null>"; - log->Printf ("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); - } + log->Printf("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__, + force ? "true" : "false", arch_name, triple_cstr); + } - bool create = force; - if (create == false && arch && arch->IsValid()) - { - const llvm::Triple &triple = arch->GetTriple(); - switch (triple.getVendor()) - { - case llvm::Triple::PC: - create = true; - break; + bool create = force; + if (create == false && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + switch (triple.getVendor()) { + case llvm::Triple::PC: + create = true; + break; #if defined(__ANDROID__) - // Only accept "unknown" for the vendor if the host is android and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified_ - case llvm::Triple::VendorType::UnknownVendor: - create = !arch->TripleVendorWasSpecified(); - break; + // Only accept "unknown" for the vendor if the host is android and + // it "unknown" wasn't specified (it was just returned because it + // was NOT specified_ + case llvm::Triple::VendorType::UnknownVendor: + create = !arch->TripleVendorWasSpecified(); + break; #endif - default: - break; - } - - if (create) - { - switch (triple.getOS()) - { - case llvm::Triple::Android: - break; + default: + break; + } + + if (create) { + switch (triple.getOS()) { + case llvm::Triple::Android: + break; #if defined(__ANDROID__) - // Only accept "unknown" for the OS if the host is android and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) - case llvm::Triple::OSType::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; + // Only accept "unknown" for the OS if the host is android and + // it "unknown" wasn't specified (it was just returned because it + // was NOT specified) + case llvm::Triple::OSType::UnknownOS: + create = !arch->TripleOSWasSpecified(); + break; #endif - default: - create = false; - break; - } - } - } - - if (create) - { - if (log) - log->Printf ("PlatformAndroid::%s() creating remote-android platform", __FUNCTION__); - return PlatformSP(new PlatformAndroid(false)); + default: + create = false; + break; + } } + } + if (create) { if (log) - log->Printf ("PlatformAndroid::%s() aborting creation of remote-android platform", __FUNCTION__); + log->Printf("PlatformAndroid::%s() creating remote-android platform", + __FUNCTION__); + return PlatformSP(new PlatformAndroid(false)); + } - return PlatformSP(); -} + if (log) + log->Printf( + "PlatformAndroid::%s() aborting creation of remote-android platform", + __FUNCTION__); -PlatformAndroid::PlatformAndroid (bool is_host) : - PlatformLinux(is_host), - m_sdk_version(0) -{ + return PlatformSP(); } -PlatformAndroid::~PlatformAndroid() -{ -} +PlatformAndroid::PlatformAndroid(bool is_host) + : PlatformLinux(is_host), m_sdk_version(0) {} -ConstString -PlatformAndroid::GetPluginNameStatic (bool is_host) -{ - if (is_host) - { - static ConstString g_host_name(Platform::GetHostPlatformName ()); - return g_host_name; - } - else - { - static ConstString g_remote_name("remote-android"); - return g_remote_name; - } -} +PlatformAndroid::~PlatformAndroid() {} -const char * -PlatformAndroid::GetPluginDescriptionStatic (bool is_host) -{ - if (is_host) - return "Local Android user platform plug-in."; - else - return "Remote Android user platform plug-in."; +ConstString PlatformAndroid::GetPluginNameStatic(bool is_host) { + if (is_host) { + static ConstString g_host_name(Platform::GetHostPlatformName()); + return g_host_name; + } else { + static ConstString g_remote_name("remote-android"); + return g_remote_name; + } } -ConstString -PlatformAndroid::GetPluginName() -{ - return GetPluginNameStatic(IsHost()); +const char *PlatformAndroid::GetPluginDescriptionStatic(bool is_host) { + if (is_host) + return "Local Android user platform plug-in."; + else + return "Remote Android user platform plug-in."; } -Error -PlatformAndroid::ConnectRemote(Args& args) -{ - m_device_id.clear(); +ConstString PlatformAndroid::GetPluginName() { + return GetPluginNameStatic(IsHost()); +} - if (IsHost()) - { - return Error ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); - } +Error PlatformAndroid::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (IsHost()) { + return Error("can't connect to the host platform '%s', always connected", + GetPluginName().GetCString()); + } + + if (!m_remote_platform_sp) + m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); + + int port; + std::string scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Error("URL is null."); + if (!UriParser::Parse(url, scheme, host, port, path)) + return Error("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = host; + + auto error = PlatformLinux::ConnectRemote(args); + if (error.Success()) { + AdbClient adb; + error = AdbClient::CreateByDeviceID(m_device_id, adb); + if (error.Fail()) + return error; - if (!m_remote_platform_sp) - m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer()); - - int port; - std::string scheme, host, path; - const char *url = args.GetArgumentAtIndex(0); - if (!url) - return Error("URL is null."); - if (!UriParser::Parse(url, scheme, host, port, path)) - return Error("Invalid URL: %s", url); - if (host != "localhost") - m_device_id = host; - - auto error = PlatformLinux::ConnectRemote(args); - if (error.Success()) - { - AdbClient adb; - error = AdbClient::CreateByDeviceID(m_device_id, adb); - if (error.Fail()) - return error; - - m_device_id = adb.GetDeviceID(); - } - return error; + m_device_id = adb.GetDeviceID(); + } + return error; } -Error -PlatformAndroid::GetFile (const FileSpec& source, - const FileSpec& destination) -{ - if (IsHost() || !m_remote_platform_sp) - return PlatformLinux::GetFile(source, destination); +Error PlatformAndroid::GetFile(const FileSpec &source, + const FileSpec &destination) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::GetFile(source, destination); - FileSpec source_spec (source.GetPath (false), false, FileSpec::ePathSyntaxPosix); - if (source_spec.IsRelative()) - source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false)); + FileSpec source_spec(source.GetPath(false), false, + FileSpec::ePathSyntaxPosix); + if (source_spec.IsRelative()) + source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + source_spec.GetCString(false)); - Error error; - auto sync_service = GetSyncService (error); - if (error.Fail ()) - return error; + Error error; + auto sync_service = GetSyncService(error); + if (error.Fail()) + return error; - uint32_t mode = 0, size = 0, mtime = 0; - error = sync_service->Stat(source_spec, mode, size, mtime); - if (error.Fail()) - return error; + uint32_t mode = 0, size = 0, mtime = 0; + error = sync_service->Stat(source_spec, mode, size, mtime); + if (error.Fail()) + return error; - if (mode != 0) - return sync_service->PullFile(source_spec, destination); + if (mode != 0) + return sync_service->PullFile(source_spec, destination); - auto source_file = source_spec.GetCString(false); + auto source_file = source_spec.GetCString(false); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", + source_file); - if (strchr(source_file, '\'') != nullptr) - return Error("Doesn't support single-quotes in filenames"); + if (strchr(source_file, '\'') != nullptr) + return Error("Doesn't support single-quotes in filenames"); - // mode == 0 can signify that adbd cannot access the file - // due security constraints - try "cat ..." as a fallback. - AdbClient adb(m_device_id); + // mode == 0 can signify that adbd cannot access the file + // due security constraints - try "cat ..." as a fallback. + AdbClient adb(m_device_id); - char cmd[PATH_MAX]; - snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + char cmd[PATH_MAX]; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); - return adb.ShellToFile(cmd, 60000 /* ms */, destination); + return adb.ShellToFile(cmd, 60000 /* ms */, destination); } -Error -PlatformAndroid::PutFile (const FileSpec& source, - const FileSpec& destination, - uint32_t uid, - uint32_t gid) -{ - if (IsHost() || !m_remote_platform_sp) - return PlatformLinux::PutFile (source, destination, uid, gid); - - FileSpec destination_spec (destination.GetPath (false), false, FileSpec::ePathSyntaxPosix); - if (destination_spec.IsRelative()) - destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false)); - - // TODO: Set correct uid and gid on remote file. - Error error; - auto sync_service = GetSyncService (error); - if (error.Fail ()) - return error; - return sync_service->PushFile(source, destination_spec); +Error PlatformAndroid::PutFile(const FileSpec &source, + const FileSpec &destination, uint32_t uid, + uint32_t gid) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::PutFile(source, destination, uid, gid); + + FileSpec destination_spec(destination.GetPath(false), false, + FileSpec::ePathSyntaxPosix); + if (destination_spec.IsRelative()) + destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + destination_spec.GetCString(false)); + + // TODO: Set correct uid and gid on remote file. + Error error; + auto sync_service = GetSyncService(error); + if (error.Fail()) + return error; + return sync_service->PushFile(source, destination_spec); } -const char * -PlatformAndroid::GetCacheHostname () -{ - return m_device_id.c_str (); -} +const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); } -Error -PlatformAndroid::DownloadModuleSlice (const FileSpec &src_file_spec, - const uint64_t src_offset, - const uint64_t src_size, - const FileSpec &dst_file_spec) -{ - if (src_offset != 0) - return Error ("Invalid offset - %" PRIu64, src_offset); +Error PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, + const uint64_t src_size, + const FileSpec &dst_file_spec) { + if (src_offset != 0) + return Error("Invalid offset - %" PRIu64, src_offset); - return GetFile (src_file_spec, dst_file_spec); + return GetFile(src_file_spec, dst_file_spec); } -Error -PlatformAndroid::DisconnectRemote() -{ - Error error = PlatformLinux::DisconnectRemote(); - if (error.Success()) - { - m_device_id.clear(); - m_sdk_version = 0; - } - return error; +Error PlatformAndroid::DisconnectRemote() { + Error error = PlatformLinux::DisconnectRemote(); + if (error.Success()) { + m_device_id.clear(); + m_sdk_version = 0; + } + return error; } -uint32_t -PlatformAndroid::GetDefaultMemoryCacheLineSize() -{ - return g_android_default_cache_size; +uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() { + return g_android_default_cache_size; } -uint32_t -PlatformAndroid::GetSdkVersion() -{ - if (!IsConnected()) - return 0; - - if (m_sdk_version != 0) - return m_sdk_version; - - std::string version_string; - AdbClient adb(m_device_id); - Error error = adb.Shell("getprop ro.build.version.sdk", 5000 /* ms */, &version_string); - version_string = llvm::StringRef(version_string).trim().str(); - - if (error.Fail() || version_string.empty()) - { - Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM); - if (log) - log->Printf("Get SDK version failed. (error: %s, output: %s)", - error.AsCString(), version_string.c_str()); - return 0; - } +uint32_t PlatformAndroid::GetSdkVersion() { + if (!IsConnected()) + return 0; - m_sdk_version = StringConvert::ToUInt32(version_string.c_str()); + if (m_sdk_version != 0) return m_sdk_version; + + std::string version_string; + AdbClient adb(m_device_id); + Error error = + adb.Shell("getprop ro.build.version.sdk", 5000 /* ms */, &version_string); + version_string = llvm::StringRef(version_string).trim().str(); + + if (error.Fail() || version_string.empty()) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM); + if (log) + log->Printf("Get SDK version failed. (error: %s, output: %s)", + error.AsCString(), version_string.c_str()); + return 0; + } + + m_sdk_version = StringConvert::ToUInt32(version_string.c_str()); + return m_sdk_version; } -Error -PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp, - const FileSpec& dst_file_spec) -{ - // For oat file we can try to fetch additional debug info from the device - ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); - if (extension != ConstString("oat") && extension != ConstString("odex")) - return Error("Symbol file downloading only supported for oat and odex files"); - - // If we have no information about the platform file we can't execute oatdump - if (!module_sp->GetPlatformFileSpec()) - return Error("No platform file specified"); - - // Symbolizer isn't available before SDK version 23 - if (GetSdkVersion() < 23) - return Error("Symbol file generation only supported on SDK 23+"); - - // If we already have symtab then we don't have to try and generate one - if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != nullptr) - return Error("Symtab already available in the module"); - - AdbClient adb(m_device_id); - 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 = llvm::StringRef(tmpdir).trim().str(); - - // Create file remover for the temporary directory created on the device - std::unique_ptr<std::string, std::function<void(std::string*)>> tmpdir_remover( - &tmpdir, - [this, &adb](std::string* s) { - StreamString command; - command.Printf("rm -rf %s", s->c_str()); - Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr); - - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); - if (log && error.Fail()) - log->Printf("Failed to remove temp directory: %s", error.AsCString()); - } - ); - - FileSpec symfile_platform_filespec(tmpdir.c_str(), false); - symfile_platform_filespec.AppendPathComponent("symbolized.oat"); - - // Execute oatdump on the remote device to generate a file with symtab +Error PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &dst_file_spec) { + // For oat file we can try to fetch additional debug info from the device + ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); + if (extension != ConstString("oat") && extension != ConstString("odex")) + return Error( + "Symbol file downloading only supported for oat and odex files"); + + // If we have no information about the platform file we can't execute oatdump + if (!module_sp->GetPlatformFileSpec()) + return Error("No platform file specified"); + + // Symbolizer isn't available before SDK version 23 + if (GetSdkVersion() < 23) + return Error("Symbol file generation only supported on SDK 23+"); + + // If we already have symtab then we don't have to try and generate one + if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) != + nullptr) + return Error("Symtab already available in the module"); + + AdbClient adb(m_device_id); + 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 = llvm::StringRef(tmpdir).trim().str(); + + // Create file remover for the temporary directory created on the device + std::unique_ptr<std::string, std::function<void(std::string *)>> + tmpdir_remover(&tmpdir, [this, &adb](std::string *s) { StreamString command; - command.Printf("oatdump --symbolize=%s --output=%s", - module_sp->GetPlatformFileSpec().GetCString(false), - symfile_platform_filespec.GetCString(false)); - error = adb.Shell(command.GetData(), 60000 /* ms */, nullptr); - if (error.Fail()) - return Error("Oatdump failed: %s", error.AsCString()); + command.Printf("rm -rf %s", s->c_str()); + Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr); - // Download the symbolfile from the remote device - return GetFile(symfile_platform_filespec, dst_file_spec); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log && error.Fail()) + log->Printf("Failed to remove temp directory: %s", error.AsCString()); + }); + + FileSpec symfile_platform_filespec(tmpdir.c_str(), false); + symfile_platform_filespec.AppendPathComponent("symbolized.oat"); + + // Execute oatdump on the remote device to generate a file with symtab + StreamString command; + command.Printf("oatdump --symbolize=%s --output=%s", + module_sp->GetPlatformFileSpec().GetCString(false), + symfile_platform_filespec.GetCString(false)); + 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 + return GetFile(symfile_platform_filespec, dst_file_spec); } -bool -PlatformAndroid::GetRemoteOSVersion () -{ - m_major_os_version = GetSdkVersion(); - m_minor_os_version = 0; - m_update_os_version = 0; - return m_major_os_version != 0; +bool PlatformAndroid::GetRemoteOSVersion() { + m_major_os_version = GetSdkVersion(); + m_minor_os_version = 0; + m_update_os_version = 0; + return m_major_os_version != 0; } -const char* -PlatformAndroid::GetLibdlFunctionDeclarations() const -{ - return R"( +const char *PlatformAndroid::GetLibdlFunctionDeclarations() const { + return R"( extern "C" void* dlopen(const char*, int) asm("__dl_dlopen"); extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym"); extern "C" int dlclose(void*) asm("__dl_dlclose"); @@ -419,14 +377,11 @@ PlatformAndroid::GetLibdlFunctionDeclarations() const )"; } -AdbClient::SyncService* -PlatformAndroid::GetSyncService (Error &error) -{ - if (m_adb_sync_svc && m_adb_sync_svc->IsConnected ()) - return m_adb_sync_svc.get (); +AdbClient::SyncService *PlatformAndroid::GetSyncService(Error &error) { + if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) + return m_adb_sync_svc.get(); - AdbClient adb (m_device_id); - m_adb_sync_svc = adb.GetSyncService (error); - return (error.Success ()) ? m_adb_sync_svc.get () : nullptr; + AdbClient adb(m_device_id); + m_adb_sync_svc = adb.GetSyncService(error); + return (error.Success()) ? m_adb_sync_svc.get() : nullptr; } - diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h index 6f7a87ca9fe..8417055733f 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h @@ -24,95 +24,69 @@ namespace lldb_private { namespace platform_android { - class PlatformAndroid : public platform_linux::PlatformLinux - { - public: - PlatformAndroid(bool is_host); - - ~PlatformAndroid() override; - - static void - Initialize (); - - static void - Terminate (); - - //------------------------------------------------------------ - // lldb_private::PluginInterface functions - //------------------------------------------------------------ - static lldb::PlatformSP - CreateInstance (bool force, const ArchSpec *arch); - - static ConstString - GetPluginNameStatic (bool is_host); - - static const char * - GetPluginDescriptionStatic (bool is_host); - - ConstString - GetPluginName() override; - - uint32_t - GetPluginVersion() override - { - return 1; - } - - //------------------------------------------------------------ - // lldb_private::Platform functions - //------------------------------------------------------------ - - Error - ConnectRemote (Args& args) override; - - Error - GetFile (const FileSpec& source, - const FileSpec& destination) override; - - Error - PutFile (const FileSpec& source, - const FileSpec& destination, - uint32_t uid = UINT32_MAX, - uint32_t gid = UINT32_MAX) override; - - uint32_t - GetSdkVersion(); - - bool - GetRemoteOSVersion() override; - - Error - DisconnectRemote () override; - - uint32_t - GetDefaultMemoryCacheLineSize() override; - - protected: - const char * - GetCacheHostname () override; - - Error - DownloadModuleSlice (const FileSpec &src_file_spec, - const uint64_t src_offset, - const uint64_t src_size, - const FileSpec &dst_file_spec) override; - - Error - DownloadSymbolFile (const lldb::ModuleSP& module_sp, - const FileSpec& dst_file_spec) override; - - const char* - GetLibdlFunctionDeclarations() const override; - - private: - AdbClient::SyncService* GetSyncService (Error &error); - - std::unique_ptr<AdbClient::SyncService> m_adb_sync_svc; - std::string m_device_id; - uint32_t m_sdk_version; - - DISALLOW_COPY_AND_ASSIGN (PlatformAndroid); - }; +class PlatformAndroid : public platform_linux::PlatformLinux { +public: + PlatformAndroid(bool is_host); + + ~PlatformAndroid() override; + + static void Initialize(); + + static void Terminate(); + + //------------------------------------------------------------ + // lldb_private::PluginInterface functions + //------------------------------------------------------------ + static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch); + + static ConstString GetPluginNameStatic(bool is_host); + + static const char *GetPluginDescriptionStatic(bool is_host); + + ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override { return 1; } + + //------------------------------------------------------------ + // lldb_private::Platform functions + //------------------------------------------------------------ + + Error ConnectRemote(Args &args) override; + + Error GetFile(const FileSpec &source, const FileSpec &destination) override; + + Error PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; + + uint32_t GetSdkVersion(); + + bool GetRemoteOSVersion() override; + + Error DisconnectRemote() override; + + uint32_t GetDefaultMemoryCacheLineSize() override; + +protected: + const char *GetCacheHostname() override; + + Error DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, const uint64_t src_size, + const FileSpec &dst_file_spec) override; + + Error DownloadSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &dst_file_spec) override; + + const char *GetLibdlFunctionDeclarations() const override; + +private: + AdbClient::SyncService *GetSyncService(Error &error); + + std::unique_ptr<AdbClient::SyncService> m_adb_sync_svc; + std::string m_device_id; + uint32_t m_sdk_version; + + DISALLOW_COPY_AND_ASSIGN(PlatformAndroid); +}; } // namespace platofor_android } // namespace lldb_private diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index f11f2874e35..239ac578321 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -10,8 +10,8 @@ // Other libraries and framework includes #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" -#include "lldb/Host/common/TCPSocket.h" #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" #include "PlatformAndroidRemoteGDBServer.h" #include "Utility/UriParser.h" @@ -22,241 +22,211 @@ using namespace lldb; using namespace lldb_private; using namespace platform_android; -static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform - -static Error -ForwardPortWithAdb (const uint16_t local_port, - const uint16_t remote_port, - const char* remote_socket_name, - const llvm::Optional<AdbClient::UnixSocketNamespace>& socket_namespace, - std::string& device_id) -{ - Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); +static const lldb::pid_t g_remote_platform_pid = + 0; // Alias for the process id of lldb-platform - AdbClient adb; - auto error = AdbClient::CreateByDeviceID(device_id, adb); - if (error.Fail ()) - return error; +static Error ForwardPortWithAdb( + const uint16_t local_port, const uint16_t remote_port, + const char *remote_socket_name, + const llvm::Optional<AdbClient::UnixSocketNamespace> &socket_namespace, + std::string &device_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - device_id = adb.GetDeviceID(); - if (log) - log->Printf("Connected to Android device \"%s\"", device_id.c_str ()); + AdbClient adb; + auto error = AdbClient::CreateByDeviceID(device_id, adb); + if (error.Fail()) + return error; - if (remote_port != 0) - { - if (log) - log->Printf("Forwarding remote TCP port %d to local TCP port %d", remote_port, local_port); - return adb.SetPortForwarding(local_port, remote_port); - } + device_id = adb.GetDeviceID(); + if (log) + log->Printf("Connected to Android device \"%s\"", device_id.c_str()); + if (remote_port != 0) { if (log) - log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", remote_socket_name, local_port); + log->Printf("Forwarding remote TCP port %d to local TCP port %d", + remote_port, local_port); + return adb.SetPortForwarding(local_port, remote_port); + } - if (!socket_namespace) - return Error("Invalid socket namespace"); + if (log) + log->Printf("Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name, local_port); - return adb.SetPortForwarding(local_port, remote_socket_name, *socket_namespace); + if (!socket_namespace) + return Error("Invalid socket namespace"); + + return adb.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); } -static Error -DeleteForwardPortWithAdb (uint16_t local_port, const std::string& device_id) -{ - AdbClient adb (device_id); - return adb.DeletePortForwarding (local_port); +static Error DeleteForwardPortWithAdb(uint16_t local_port, + const std::string &device_id) { + AdbClient adb(device_id); + return adb.DeletePortForwarding(local_port); } -static Error -FindUnusedPort (uint16_t& port) -{ - Error error; - std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error)); - if (error.Fail()) - return error; +static Error FindUnusedPort(uint16_t &port) { + Error error; + std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error)); + if (error.Fail()) + return error; - error = tcp_socket->Listen("127.0.0.1:0", 1); - if (error.Success()) - port = tcp_socket->GetLocalPortNumber(); + error = tcp_socket->Listen("127.0.0.1:0", 1); + if (error.Success()) + port = tcp_socket->GetLocalPortNumber(); - return error; + return error; } -PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer () -{ -} +PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer() {} -PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer () -{ - for (const auto& it : m_port_forwards) - DeleteForwardPortWithAdb(it.second, m_device_id); +PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer() { + for (const auto &it : m_port_forwards) + DeleteForwardPortWithAdb(it.second, m_device_id); } -bool -PlatformAndroidRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) -{ - uint16_t remote_port = 0; - std::string socket_name; - if (!m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, remote_port, socket_name)) - return false; +bool PlatformAndroidRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid, + std::string &connect_url) { + uint16_t remote_port = 0; + std::string socket_name; + if (!m_gdb_client.LaunchGDBServer("127.0.0.1", pid, remote_port, socket_name)) + return false; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - auto error = MakeConnectURL (pid, - remote_port, - socket_name.c_str (), - connect_url); - if (error.Success() && log) - log->Printf("gdbserver connect URL: %s", connect_url.c_str()); + auto error = + MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); + if (error.Success() && log) + log->Printf("gdbserver connect URL: %s", connect_url.c_str()); - return error.Success(); + return error.Success(); } -bool -PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid) -{ - DeleteForwardPort (pid); - return m_gdb_client.KillSpawnedProcess (pid); +bool PlatformAndroidRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { + DeleteForwardPort(pid); + return m_gdb_client.KillSpawnedProcess(pid); } -Error -PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args) -{ - m_device_id.clear(); - - if (args.GetArgumentCount() != 1) - return Error("\"platform connect\" takes a single argument: <connect-url>"); - - int remote_port; - std::string scheme, host, path; - const char *url = args.GetArgumentAtIndex (0); - if (!url) - return Error("URL is null."); - if (!UriParser::Parse (url, scheme, host, remote_port, path)) - return Error("Invalid URL: %s", url); - if (host != "localhost") - m_device_id = host; - - m_socket_namespace.reset(); - if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME) - m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem; - else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME) - m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract; - - std::string connect_url; - auto error = MakeConnectURL (g_remote_platform_pid, - (remote_port < 0) ? 0 : remote_port, - path.c_str (), - connect_url); - - if (error.Fail ()) - return error; - - args.ReplaceArgumentAtIndex (0, connect_url.c_str ()); - - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); +Error PlatformAndroidRemoteGDBServer::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (args.GetArgumentCount() != 1) + return Error("\"platform connect\" takes a single argument: <connect-url>"); + + int remote_port; + std::string scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Error("URL is null."); + if (!UriParser::Parse(url, scheme, host, remote_port, path)) + return Error("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = host; + + m_socket_namespace.reset(); + if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME) + m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem; + else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME) + m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract; + + std::string connect_url; + auto error = + MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port, + path.c_str(), connect_url); + + if (error.Fail()) + return error; - error = PlatformRemoteGDBServer::ConnectRemote(args); - if (error.Fail ()) - DeleteForwardPort (g_remote_platform_pid); + args.ReplaceArgumentAtIndex(0, connect_url.c_str()); - return error; -} + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Rewritten platform connect URL: %s", connect_url.c_str()); -Error -PlatformAndroidRemoteGDBServer::DisconnectRemote () -{ - DeleteForwardPort (g_remote_platform_pid); - return PlatformRemoteGDBServer::DisconnectRemote (); + error = PlatformRemoteGDBServer::ConnectRemote(args); + if (error.Fail()) + DeleteForwardPort(g_remote_platform_pid); + + return error; } -void -PlatformAndroidRemoteGDBServer::DeleteForwardPort (lldb::pid_t pid) -{ - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - - auto it = m_port_forwards.find(pid); - if (it == m_port_forwards.end()) - return; - - const auto port = it->second; - const auto error = DeleteForwardPortWithAdb(port, m_device_id); - if (error.Fail()) { - if (log) - log->Printf("Failed to delete port forwarding (pid=%" PRIu64 ", port=%d, device=%s): %s", - pid, port, m_device_id.c_str(), error.AsCString()); - } - m_port_forwards.erase(it); +Error PlatformAndroidRemoteGDBServer::DisconnectRemote() { + DeleteForwardPort(g_remote_platform_pid); + return PlatformRemoteGDBServer::DisconnectRemote(); } -Error -PlatformAndroidRemoteGDBServer::MakeConnectURL(const lldb::pid_t pid, - const uint16_t remote_port, - const char* remote_socket_name, - std::string& connect_url) -{ - static const int kAttempsNum = 5; - - Error error; - // There is a race possibility that somebody will occupy - // a port while we're in between FindUnusedPort and ForwardPortWithAdb - - // adding the loop to mitigate such problem. - for (auto i = 0; i < kAttempsNum; ++i) - { - uint16_t local_port = 0; - error = FindUnusedPort(local_port); - if (error.Fail()) - return error; - - error = ForwardPortWithAdb(local_port, - remote_port, - remote_socket_name, - m_socket_namespace, - m_device_id); - if (error.Success()) - { - m_port_forwards[pid] = local_port; - std::ostringstream url_str; - url_str << "connect://localhost:" << local_port; - connect_url = url_str.str(); - break; - } - } +void PlatformAndroidRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); - return error; + auto it = m_port_forwards.find(pid); + if (it == m_port_forwards.end()) + return; + + const auto port = it->second; + const auto error = DeleteForwardPortWithAdb(port, m_device_id); + if (error.Fail()) { + if (log) + log->Printf("Failed to delete port forwarding (pid=%" PRIu64 + ", port=%d, device=%s): %s", + pid, port, m_device_id.c_str(), error.AsCString()); + } + m_port_forwards.erase(it); } -lldb::ProcessSP -PlatformAndroidRemoteGDBServer::ConnectProcess(const char* connect_url, - const char* plugin_name, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Error &error) -{ - // We don't have the pid of the remote gdbserver when it isn't started by us but we still want - // to store the list of port forwards we set up in our port forward map. Generate a fake pid for - // these cases what won't collide with any other valid pid on android. - static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; - - int remote_port; - std::string scheme, host, path; - if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) - { - error.SetErrorStringWithFormat("Invalid URL: %s", connect_url); - return nullptr; +Error PlatformAndroidRemoteGDBServer::MakeConnectURL( + const lldb::pid_t pid, const uint16_t remote_port, + const char *remote_socket_name, std::string &connect_url) { + static const int kAttempsNum = 5; + + Error error; + // There is a race possibility that somebody will occupy + // a port while we're in between FindUnusedPort and ForwardPortWithAdb - + // adding the loop to mitigate such problem. + for (auto i = 0; i < kAttempsNum; ++i) { + uint16_t local_port = 0; + error = FindUnusedPort(local_port); + if (error.Fail()) + return error; + + error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name, + m_socket_namespace, m_device_id); + if (error.Success()) { + m_port_forwards[pid] = local_port; + std::ostringstream url_str; + url_str << "connect://localhost:" << local_port; + connect_url = url_str.str(); + break; } + } - std::string new_connect_url; - error = MakeConnectURL(s_remote_gdbserver_fake_pid--, - (remote_port < 0) ? 0 : remote_port, - path.c_str(), - new_connect_url); - if (error.Fail()) - return nullptr; + return error; +} - return PlatformRemoteGDBServer::ConnectProcess(new_connect_url.c_str(), - plugin_name, - debugger, - target, - error); +lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess( + const char *connect_url, const char *plugin_name, + lldb_private::Debugger &debugger, lldb_private::Target *target, + lldb_private::Error &error) { + // We don't have the pid of the remote gdbserver when it isn't started by us + // but we still want + // to store the list of port forwards we set up in our port forward map. + // Generate a fake pid for + // these cases what won't collide with any other valid pid on android. + static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL; + + int remote_port; + std::string scheme, host, path; + if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) { + error.SetErrorStringWithFormat("Invalid URL: %s", connect_url); + return nullptr; + } + + std::string new_connect_url; + error = MakeConnectURL(s_remote_gdbserver_fake_pid--, + (remote_port < 0) ? 0 : remote_port, path.c_str(), + new_connect_url); + if (error.Fail()) + return nullptr; + + return PlatformRemoteGDBServer::ConnectProcess( + new_connect_url.c_str(), plugin_name, debugger, target, error); } diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h index 79e273c665e..9748c86b969 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -26,48 +26,40 @@ namespace lldb_private { namespace platform_android { -class PlatformAndroidRemoteGDBServer : public platform_gdb_server::PlatformRemoteGDBServer -{ +class PlatformAndroidRemoteGDBServer + : public platform_gdb_server::PlatformRemoteGDBServer { public: - PlatformAndroidRemoteGDBServer(); + PlatformAndroidRemoteGDBServer(); - ~PlatformAndroidRemoteGDBServer() override; + ~PlatformAndroidRemoteGDBServer() override; - Error - ConnectRemote (Args& args) override; + Error ConnectRemote(Args &args) override; - Error - DisconnectRemote () override; + Error DisconnectRemote() override; - lldb::ProcessSP - ConnectProcess (const char* connect_url, - const char* plugin_name, - lldb_private::Debugger &debugger, - lldb_private::Target *target, - lldb_private::Error &error) override; + lldb::ProcessSP ConnectProcess(const char *connect_url, + const char *plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Error &error) override; protected: - std::string m_device_id; - std::map<lldb::pid_t, uint16_t> m_port_forwards; - llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace; + std::string m_device_id; + std::map<lldb::pid_t, uint16_t> m_port_forwards; + llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace; - bool - LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url) override; + bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; - bool - KillSpawnedProcess (lldb::pid_t pid) override; + bool KillSpawnedProcess(lldb::pid_t pid) override; - void - DeleteForwardPort (lldb::pid_t pid); + void DeleteForwardPort(lldb::pid_t pid); - Error - MakeConnectURL(const lldb::pid_t pid, - const uint16_t remote_port, - const char* remote_socket_name, - std::string& connect_url); + Error MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, + const char *remote_socket_name, + std::string &connect_url); private: - DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer); + DISALLOW_COPY_AND_ASSIGN(PlatformAndroidRemoteGDBServer); }; } // namespace platform_android |