From 4314ace9ec79326ee4e7388cbde29f96ba6a63ae Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Mon, 19 Sep 2022 11:52:31 +0800 Subject: [PATCH 01/10] =?UTF-8?q?[LLDB]=20[BUG]=20Add=20=E2=80=9Cremote-ho?= =?UTF-8?q?s=E2=80=9D=20and=20do=20not=20use=20=E2=80=9CAdbClient=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xwx1135370 --- lldb/source/Plugins/Platform/Android/AdbClient.cpp | 2 +- lldb/source/Plugins/Platform/CMakeLists.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp index 50a4a07a9bab..ffccd6d628aa 100644 --- a/lldb/source/Plugins/Platform/Android/AdbClient.cpp +++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp @@ -134,7 +134,7 @@ Status AdbClient::Connect() { Status error; m_conn = std::make_unique(); std::string port = "5037"; - if (const char *env_port = std::getenv("HDC_SERVER_PORT")) { + if (const char *env_port = std::getenv("ANDROID_ADB_SERVER_PORT")) { port = env_port; } std::string uri = "connect://127.0.0.1:" + port; diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt index 8c532955a9dd..c312beb80b7c 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -15,4 +15,5 @@ add_subdirectory(POSIX) add_subdirectory(gdb-server) add_subdirectory(Android) +add_subdirectory(HOS) add_subdirectory(OHOS) -- Gitee From 2dd7c9c5feff9aaaad2b1c4d2170ef244450a475 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Mon, 19 Sep 2022 11:54:59 +0800 Subject: [PATCH 02/10] =?UTF-8?q?[LLDB]=20[BUG]=20Add=20=E2=80=9Cremote-ho?= =?UTF-8?q?s=E2=80=9D=20and=20do=20not=20use=20=E2=80=9CAdbClient=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xwx1135370 --- .../Plugins/Platform/HOS/CMakeLists.txt | 13 + .../source/Plugins/Platform/HOS/HdcClient.cpp | 662 ++++++++++++++++++ lldb/source/Plugins/Platform/HOS/HdcClient.h | 138 ++++ .../Plugins/Platform/HOS/PlatformHOS.cpp | 374 ++++++++++ .../source/Plugins/Platform/HOS/PlatformHOS.h | 85 +++ .../HOS/PlatformHOSRemoteGDBServer.cpp | 226 ++++++ .../Platform/HOS/PlatformHOSRemoteGDBServer.h | 66 ++ 7 files changed, 1564 insertions(+) create mode 100644 lldb/source/Plugins/Platform/HOS/CMakeLists.txt create mode 100644 lldb/source/Plugins/Platform/HOS/HdcClient.cpp create mode 100644 lldb/source/Plugins/Platform/HOS/HdcClient.h create mode 100644 lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp create mode 100644 lldb/source/Plugins/Platform/HOS/PlatformHOS.h create mode 100644 lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp create mode 100644 lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h diff --git a/lldb/source/Plugins/Platform/HOS/CMakeLists.txt b/lldb/source/Plugins/Platform/HOS/CMakeLists.txt new file mode 100644 index 000000000000..7234e578633b --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/CMakeLists.txt @@ -0,0 +1,13 @@ +add_lldb_library(lldbPluginPlatformHOS PLUGIN + HdcClient.cpp + PlatformHOS.cpp + PlatformHOSRemoteGDBServer.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbPluginPlatformLinux + lldbPluginPlatformGDB + LINK_COMPONENTS + Support + ) \ No newline at end of file diff --git a/lldb/source/Plugins/Platform/HOS/HdcClient.cpp b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp new file mode 100644 index 000000000000..d4e656fcf562 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp @@ -0,0 +1,662 @@ +//===-- HdcClient.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HdcClient.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileUtilities.h" + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/PosixApi.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/DataEncoder.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timeout.h" + +#include + +#include +#include +#include +#include + +// On Windows, transitive dependencies pull in , which defines a +// macro that clashes with a method name. +#ifdef SendMessage +#undef SendMessage +#endif + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_hos; +using namespace std::chrono; + +namespace { + +const seconds kReadTimeout(20); +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 size_t kSyncPacketLen = 8; +// Maximum size of a filesync DATA packet. +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"; + +Status ReadAllBytes(Connection &conn, void *buffer, size_t size) { + + Status error; + ConnectionStatus status; + char *read_buffer = static_cast(buffer); + + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) { + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, + duration_cast(deadline - now), 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 = Status( + "Unable to read requested number of bytes. Connection status: %d.", + status); + return error; +} + +} // namespace + +Status HdcClient::CreateByDeviceID(const std::string &device_id, + HdcClient &hdc) { + DeviceIDList connect_devices; + auto error = hdc.GetDevices(connect_devices); + 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 Status("Expected a single connected device, got instead %zu - try " + "setting 'ANDROID_SERIAL'", + connect_devices.size()); + hdc.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 Status("Device \"%s\" not found", android_serial.c_str()); + + hdc.SetDeviceID(*find_it); + } + return error; +} + +HdcClient::HdcClient() {} + +HdcClient::HdcClient(const std::string &device_id) : m_device_id(device_id) {} + +HdcClient::~HdcClient() {} + +void HdcClient::SetDeviceID(const std::string &device_id) { + m_device_id = device_id; +} + +const std::string &HdcClient::GetDeviceID() const { return m_device_id; } + +Status HdcClient::Connect() { + Status error; + m_conn.reset(new ConnectionFileDescriptor); + std::string port = "5037"; + + + + const char *env_port = std::getenv("HDC_SERVER_PORT"); + if ((env_port != NULL) && (atoi(env_port) > 0)) { + port = env_port; + } + + + std::string uri = "connect://127.0.0.1:" + port; + m_conn->Connect(uri.c_str(), &error); + + return error; +} + +Status HdcClient::GetDevices(DeviceIDList &device_list) { + device_list.clear(); + auto error = SendMessage("host:devices"); + if (error.Fail()) + return error; + + error = ReadResponseStatus(); + if (error.Fail()) + return error; + + std::vector in_buffer; + error = ReadMessage(in_buffer); + + llvm::StringRef response(&in_buffer[0], in_buffer.size()); + llvm::SmallVector devices; + response.split(devices, "\n", -1, false); + + for (const auto &device : devices) + device_list.push_back(device.split('\t').first.str()); + + // Force disconnect since hdc closes connection after host:devices response + // is sent. + m_conn.reset(); + return error; +} + +Status HdcClient::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; + + return ReadResponseStatus(); +} + +Status +HdcClient::SetPortForwarding(const uint16_t local_port, + llvm::StringRef 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.str().c_str()); + + const auto error = SendDeviceMessage(message); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::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; + + return ReadResponseStatus(); +} + +Status HdcClient::SendMessage(const std::string &packet, const bool reconnect) { + Status 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(packet.size())); + + ConnectionStatus status; + + 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; +} + +Status HdcClient::SendDeviceMessage(const std::string &packet) { + std::ostringstream msg; + msg << "host-serial:" << m_device_id << ":" << packet; + return SendMessage(msg.str()); +} + +Status HdcClient::ReadMessage(std::vector &message) { + message.clear(); + + char buffer[5]; + buffer[4] = 0; + + auto error = ReadAllBytes(buffer, 4); + if (error.Fail()) + return error; + + 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(); + + return error; +} + +Status HdcClient::ReadMessageStream(std::vector &message, + milliseconds timeout) { + auto start = steady_clock::now(); + message.clear(); + + Status error; + lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; + char buffer[1024]; + while (error.Success() && status == lldb::eConnectionStatusSuccess) { + auto end = steady_clock::now(); + auto elapsed = end - start; + if (elapsed >= timeout) + return Status("Timed out"); + + size_t n = m_conn->Read(buffer, sizeof(buffer), + duration_cast(timeout - elapsed), + status, &error); + if (n > 0) + message.insert(message.end(), &buffer[0], &buffer[n]); + } + return error; +} + +Status HdcClient::ReadResponseStatus() { + char response_id[5]; + + static const size_t packet_len = 4; + response_id[packet_len] = 0; + + auto error = ReadAllBytes(response_id, packet_len); + if (error.Fail()) + return error; + + if (strncmp(response_id, kOKAY, packet_len) != 0) + return GetResponseError(response_id); + + return error; +} + +Status HdcClient::GetResponseError(const char *response_id) { + if (strcmp(response_id, kFAIL) != 0) + return Status("Got unexpected response id from hdc: \"%s\"", response_id); + + std::vector error_message; + auto error = ReadMessage(error_message); + if (error.Success()) + error.SetErrorString( + std::string(&error_message[0], error_message.size()).c_str()); + + return error; +} + +Status HdcClient::SwitchDeviceTransport() { + std::ostringstream msg; + msg << "host:transport:" << m_device_id; + + auto error = SendMessage(msg.str()); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::StartSync() { + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Status("Failed to switch to device transport: %s", + error.AsCString()); + + error = Sync(); + if (error.Fail()) + return Status("Sync failed: %s", error.AsCString()); + + return error; +} + +Status HdcClient::Sync() { + auto error = SendMessage("sync:", false); + if (error.Fail()) + return error; + + return ReadResponseStatus(); +} + +Status HdcClient::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); +} + +Status HdcClient::internalShell(const char *command, milliseconds timeout, + std::vector &output_buf) { + output_buf.clear(); + + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Status("Failed to switch to device transport: %s", + error.AsCString()); + + StreamString hdc_command; + hdc_command.Printf("shell:%s", command); + error = SendMessage(hdc_command.GetString().str(), false); + if (error.Fail()) + return error; + + error = ReadResponseStatus(); + if (error.Fail()) + return error; + + error = ReadMessageStream(output_buf, timeout); + if (error.Fail()) + return error; + + // HDC 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 Status("Shell command %s failed: %s", command, + std::string(output_buf.begin(), output_buf.end()).c_str()); + } + + return Status(); +} + +Status HdcClient::Shell(const char *command, milliseconds timeout, + std::string *output) { + std::vector output_buffer; + auto error = internalShell(command, timeout, output_buffer); + if (error.Fail()) + return error; + + if (output) + output->assign(output_buffer.begin(), output_buffer.end()); + return error; +} + +Status HdcClient::ShellToFile(const char *command, milliseconds timeout, + const FileSpec &output_file_spec) { + std::vector output_buffer; + auto error = internalShell(command, timeout, output_buffer); + if (error.Fail()) + return error; + + const auto output_filename = output_file_spec.GetPath(); + std::error_code EC; + llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::OF_None); + if (EC) + return Status("Unable to open local file %s", output_filename.c_str()); + + dst.write(&output_buffer[0], output_buffer.size()); + dst.close(); + if (dst.has_error()) + return Status("Failed to write file %s", output_filename.c_str()); + return Status(); +} + +std::unique_ptr +HdcClient::GetSyncService(Status &error) { + std::unique_ptr sync_service; + error = StartSync(); + if (error.Success()) + sync_service.reset(new SyncService(std::move(m_conn))); + + return sync_service; +} + +Status HdcClient::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); + + std::error_code EC; + llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::OF_None); + if (EC) + return Status("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 chunk; + bool eof = false; + while (!eof) { + error = PullFileChunk(chunk, eof); + if (error.Fail()) + return error; + if (!eof) + dst.write(&chunk[0], chunk.size()); + } + dst.close(); + if (dst.has_error()) + return Status("Failed to write file %s", local_file_path.c_str()); + + local_file_remover.releaseFile(); + return error; +} + +Status HdcClient::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 Status("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 Status("Failed to send file chunk: %s", error.AsCString()); + } + error = SendSyncRequest( + kDONE, llvm::sys::toTimeT(FileSystem::Instance().GetModificationTime(local_file)), + nullptr); + if (error.Fail()) + return error; + + std::string response_id; + uint32_t data_len; + error = ReadSyncHeader(response_id, data_len); + if (error.Fail()) + return Status("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 Status("Failed to read DONE error message: %s", error.AsCString()); + return Status("Failed to push file: %s", error_message.c_str()); + } else if (response_id != kOKAY) + return Status("Got unexpected DONE response: %s", response_id.c_str()); + + // If there was an error reading the source file, finish the hdc file + // transfer first so that hdc isn't expecting any more data. + if (src.bad()) + return Status("Failed read on %s", local_file_path.c_str()); + return error; +} + +Status HdcClient::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 Status("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); + + std::vector buffer(response_len); + error = ReadAllBytes(&buffer[0], buffer.size()); + if (error.Fail()) + return Status("Failed to read response: %s", error.AsCString()); + + DataExtractor extractor(&buffer[0], buffer.size(), eByteOrderLittle, + sizeof(void *)); + offset_t offset = 0; + + const void *command = extractor.GetData(&offset, stat_len); + if (!command) + return Status("Failed to get response command"); + const char *command_str = static_cast(command); + if (strncmp(command_str, kSTAT, stat_len)) + return Status("Got invalid stat command: %s", command_str); + + mode = extractor.GetU32(&offset); + size = extractor.GetU32(&offset); + mtime = extractor.GetU32(&offset); + return Status(); +} + +Status HdcClient::SyncService::PullFile(const FileSpec &remote_file, + const FileSpec &local_file) { + return executeCommand([this, &remote_file, &local_file]() { + return internalPullFile(remote_file, local_file); + }); +} + +Status HdcClient::SyncService::PushFile(const FileSpec &local_file, + const FileSpec &remote_file) { + return executeCommand([this, &local_file, &remote_file]() { + return internalPushFile(local_file, remote_file); + }); +} + +Status HdcClient::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 HdcClient::SyncService::IsConnected() const { + return m_conn && m_conn->IsConnected(); +} + +HdcClient::SyncService::SyncService(std::unique_ptr &&conn) + : m_conn(std::move(conn)) {} + +Status +HdcClient::SyncService::executeCommand(const std::function &cmd) { + if (!m_conn) + return Status("SyncService is disconnected"); + + const auto error = cmd(); + if (error.Fail()) + m_conn.reset(); + + return error; +} + +HdcClient::SyncService::~SyncService() {} + +Status HdcClient::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.PutUnsigned(offset, 4, data_len); + + Status 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; +} + +Status HdcClient::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); + } + + return error; +} + +Status HdcClient::SyncService::PullFileChunk(std::vector &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 Status("Failed to read pull error message: %s", error.AsCString()); + return Status("Failed to pull file: %s", error_message.c_str()); + } else + return Status("Pull failed with unknown response: %s", response_id.c_str()); + + return Status(); +} + +Status HdcClient::SyncService::ReadAllBytes(void *buffer, size_t size) { + return ::ReadAllBytes(*m_conn, buffer, size); +} diff --git a/lldb/source/Plugins/Platform/HOS/HdcClient.h b/lldb/source/Plugins/Platform/HOS/HdcClient.h new file mode 100644 index 000000000000..bff51c8f8738 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/HdcClient.h @@ -0,0 +1,138 @@ +//===-- HdcClient.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_HdcClient_h_ +#define liblldb_HdcClient_h_ + +#include "lldb/Utility/Status.h" +#include +#include +#include +#include +#include +#include + +namespace lldb_private { + +class FileSpec; + +namespace platform_hos { + +class HdcClient { +public: + enum UnixSocketNamespace { + UnixSocketNamespaceAbstract, + UnixSocketNamespaceFileSystem, + }; + + using DeviceIDList = std::list; + + class SyncService { + friend class HdcClient; + + public: + ~SyncService(); + + Status PullFile(const FileSpec &remote_file, const FileSpec &local_file); + + Status PushFile(const FileSpec &local_file, const FileSpec &remote_file); + + Status Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size, + uint32_t &mtime); + + bool IsConnected() const; + + private: + explicit SyncService(std::unique_ptr &&conn); + + Status SendSyncRequest(const char *request_id, const uint32_t data_len, + const void *data); + + Status ReadSyncHeader(std::string &response_id, uint32_t &data_len); + + Status PullFileChunk(std::vector &buffer, bool &eof); + + Status ReadAllBytes(void *buffer, size_t size); + + Status internalPullFile(const FileSpec &remote_file, + const FileSpec &local_file); + + Status internalPushFile(const FileSpec &local_file, + const FileSpec &remote_file); + + Status internalStat(const FileSpec &remote_file, uint32_t &mode, + uint32_t &size, uint32_t &mtime); + + Status executeCommand(const std::function &cmd); + + std::unique_ptr m_conn; + }; + + static Status CreateByDeviceID(const std::string &device_id, HdcClient &hdc); + HdcClient(); + explicit HdcClient(const std::string &device_id); + + ~HdcClient(); + const std::string &GetDeviceID() const; + + Status GetDevices(DeviceIDList &device_list); + + Status SetPortForwarding(const uint16_t local_port, + const uint16_t remote_port); + + Status SetPortForwarding(const uint16_t local_port, + llvm::StringRef remote_socket_name, + const UnixSocketNamespace socket_namespace); + + Status DeletePortForwarding(const uint16_t local_port); + + Status Shell(const char *command, std::chrono::milliseconds timeout, + std::string *output); + + Status ShellToFile(const char *command, std::chrono::milliseconds timeout, + const FileSpec &output_file_spec); + + std::unique_ptr GetSyncService(Status &error); + + Status SwitchDeviceTransport(); + +private: + Status Connect(); + + void SetDeviceID(const std::string &device_id); + + Status SendMessage(const std::string &packet, const bool reconnect = true); + + Status SendDeviceMessage(const std::string &packet); + + Status ReadMessage(std::vector &message); + + Status ReadMessageStream(std::vector &message, + std::chrono::milliseconds timeout); + + Status GetResponseError(const char *response_id); + + Status ReadResponseStatus(); + + Status Sync(); + + Status StartSync(); + + Status internalShell(const char *command, std::chrono::milliseconds timeout, + std::vector &output_buf); + + Status ReadAllBytes(void *buffer, size_t size); + + std::string m_device_id; + std::unique_ptr m_conn; +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // liblldb_HdcClient_h_ diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp new file mode 100644 index 000000000000..c82383ddb897 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp @@ -0,0 +1,374 @@ +//===-- PlatformHOS.cpp -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Host/StringConvert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/UriParser.h" + +#include "HdcClient.h" +#include "PlatformHOS.h" +#include "PlatformHOSRemoteGDBServer.h" +#if defined __MINGW32__ +// SetEnvironmentVariableA +#include +#endif + +using namespace lldb; +using namespace lldb_private; +//using namespace lldb_private::platform_android; +using namespace lldb_private::platform_hos; +using namespace std::chrono; +static uint32_t g_initialize_count = 0; +static const unsigned int g_hos_default_cache_size = 2048; +LLDB_PLUGIN_DEFINE(PlatformHOS) + +static void platform_setenv(const char *env, const char *val) { +#if HAVE_SETENV || _MSC_VER + setenv(env, val, true); +#elif defined (__MINGW32__) + SetEnvironmentVariableA(env, val); +#else +#error "setenv not found" +#endif +} + +void PlatformHOS::Initialize() { + PlatformLinux::Initialize(); + if (g_initialize_count++ == 0) { +#if defined(__HOS__) + PlatformSP default_platform_sp(new PlatformHOS(true)); + default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); + Platform::SetHostPlatform(default_platform_sp); +#endif + PluginManager::RegisterPlugin( + PlatformHOS::GetPluginNameStatic(false), + PlatformHOS::GetPluginDescriptionStatic(false), + PlatformHOS::CreateInstance); + } +} + +void PlatformHOS::Terminate() { + if (g_initialize_count > 0) { + if (--g_initialize_count == 0) { + PluginManager::UnregisterPlugin(PlatformHOS::CreateInstance); + } + } + PlatformLinux::Terminate(); +} + +PlatformSP PlatformHOS::CreateInstance(bool force, const ArchSpec *arch) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + const char *triple_cstr = + arch ? arch->GetTriple().getTriple().c_str() : ""; + + LLDB_LOGF(log, "PlatformHOS::%s(force=%s, triple=%s)", __FUNCTION__, + force ? "true" : "false", triple_cstr); + } + + bool create = force; + if (!create && arch && arch->IsValid()) { + const llvm::Triple &triple = arch->GetTriple(); + + switch (triple.getVendor()) { + case llvm::Triple::PC: + create = true; + break; + + default: + create = triple.isOpenHOS(); + break; + + } + } + + if (create) { + if (const char *env = std::getenv("HDC_UTID")) + platform_setenv("ANDROID_SERIAL", env); + + LLDB_LOGF(log, "PlatformHOS::%s() creating remote-hos platform", + __FUNCTION__); + return PlatformSP(new PlatformHOS(false)); + } + + LLDB_LOGF( + log, "PlatformHOS::%s() aborting creation of remote-hos platform", + __FUNCTION__); + + return PlatformSP(); +} + +PlatformHOS::PlatformHOS(bool is_host) + : PlatformLinux(is_host), m_sdk_version(0) {} + +PlatformHOS::~PlatformHOS() {} + +ConstString PlatformHOS::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-hos"); + return g_remote_name; + } +} + +const char *PlatformHOS::GetPluginDescriptionStatic(bool is_host) { + if (is_host) + return "Local HarmonyOS user platform plug-in."; + else + return "Remote HarmonyOS user platform plug-in."; +} +Status PlatformHOS::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (IsHost()) { + return Status("can't connect to the host platform '%s', always connected", + GetPluginName().GetCString()); + } + + if (!m_remote_platform_sp) { + m_remote_platform_sp = PlatformSP(new PlatformHOSRemoteGDBServer()); + } + + int port; + llvm::StringRef scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + if (!UriParser::Parse(url, scheme, host, port, path)) + return Status("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = static_cast(host); + + auto error = PlatformLinux::ConnectRemote(args); + if (error.Success()) { + HdcClient hdc; + error = HdcClient::CreateByDeviceID(m_device_id, hdc); + if (error.Fail()) + return error; + + m_device_id = hdc.GetDeviceID(); + } + return error; +} + +Status PlatformHOS::GetFile(const FileSpec &source, + const FileSpec &destination) { + if (IsHost() || !m_remote_platform_sp) + return PlatformLinux::GetFile(source, destination); + + FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix); + if (source_spec.IsRelative()) + source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + source_spec.GetCString(false)); + + Status 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; + + if (mode != 0) + return sync_service->PullFile(source_spec, destination); + + auto source_file = source_spec.GetCString(false); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + LLDB_LOGF(log, "Got mode == 0 on '%s': try to get file via 'shell cat'", + source_file); + + if (strchr(source_file, '\'') != nullptr) + return Status("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. + HdcClient hdc(m_device_id); + + char cmd[PATH_MAX]; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + + return hdc.ShellToFile(cmd, minutes(1), destination); +} + +Status PlatformHOS::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), FileSpec::Style::posix); + if (destination_spec.IsRelative()) + destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent( + destination_spec.GetCString(false)); + + // TODO: Set correct uid and gid on remote file. + Status error; + auto sync_service = GetSyncService(error); + if (error.Fail()) + return error; + return sync_service->PushFile(source, destination_spec); +} + +const char *PlatformHOS::GetCacheHostname() { return m_device_id.c_str(); } + +Status PlatformHOS::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 Status("Invalid offset - %" PRIu64, src_offset); + + return GetFile(src_file_spec, dst_file_spec); +} + +Status PlatformHOS::DisconnectRemote() { + Status error = PlatformLinux::DisconnectRemote(); + if (error.Success()) { + m_device_id.clear(); + m_sdk_version = 0; + } + return error; +} + +uint32_t PlatformHOS::GetDefaultMemoryCacheLineSize() { + return g_hos_default_cache_size; +} + +uint32_t PlatformHOS::GetSdkVersion() { + if (!IsConnected()) + return 0; + + if (m_sdk_version != 0) + return m_sdk_version; + + std::string version_string; + HdcClient hdc(m_device_id); + Status error = + hdc.Shell("getprop ro.build.version.sdk", seconds(5), &version_string); + version_string = llvm::StringRef(version_string).trim().str(); + + if (error.Fail() || version_string.empty()) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM); + LLDB_LOGF(log, "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; +} + +Status PlatformHOS::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 != ".oat" && extension != ".odex") + return Status( + "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 Status("No platform file specified"); + + // Symbolizer isn't available before SDK version 23 + if (GetSdkVersion() < 23) + return Status("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 Status("Symtab already available in the module"); + + HdcClient hdc(m_device_id); + std::string tmpdir; + Status error = hdc.Shell("mktemp --directory --tmpdir /data/local/tmp", + seconds(5), &tmpdir); + if (error.Fail() || tmpdir.empty()) + return Status("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> + tmpdir_remover(&tmpdir, [&hdc](std::string *s) { + StreamString command; + command.Printf("rm -rf %s", s->c_str()); + Status error = hdc.Shell(command.GetData(), seconds(5), nullptr); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log && error.Fail()) + LLDB_LOGF(log, "Failed to remove temp directory: %s", error.AsCString()); + }); + + FileSpec symfile_platform_filespec(tmpdir); + 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 = hdc.Shell(command.GetData(), minutes(1), nullptr); + if (error.Fail()) + return Status("Oatdump failed: %s", error.AsCString()); + + // Download the symbolfile from the remote device + return GetFile(symfile_platform_filespec, dst_file_spec); +} + +bool PlatformHOS::GetRemoteOSVersion() { + m_os_version = llvm::VersionTuple(GetSdkVersion()); + return !m_os_version.empty(); +} + +llvm::StringRef +PlatformHOS::GetLibdlFunctionDeclarations(lldb_private::Process *process) { + SymbolContextList matching_symbols; + std::vector dl_open_names = { "__dl_dlopen", "dlopen" }; + const char *dl_open_name = nullptr; + Target &target = process->GetTarget(); + for (auto name: dl_open_names) { + target.GetImages().FindFunctionSymbols( + ConstString(name), eFunctionNameTypeFull, matching_symbols); + if (matching_symbols.GetSize()) { + dl_open_name = name; + break; + } + } + // Older platform versions have the dl function symbols mangled + if (dl_open_name == dl_open_names[0]) + 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"); + extern "C" char* dlerror(void) asm("__dl_dlerror"); + )"; + + return PlatformPOSIX::GetLibdlFunctionDeclarations(process); +} + +HdcClient::SyncService *PlatformHOS::GetSyncService(Status &error) { + if (m_adb_sync_svc && m_adb_sync_svc->IsConnected()) + return m_adb_sync_svc.get(); + + HdcClient hdc(m_device_id); + m_adb_sync_svc = hdc.GetSyncService(error); + return (error.Success()) ? m_adb_sync_svc.get() : nullptr; +} diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.h b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h new file mode 100644 index 000000000000..af1a8fc6f54d --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.h @@ -0,0 +1,85 @@ +//===-- PlatformHOS.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PlatformHOS_h_ +#define liblldb_PlatformHOS_h_ + +#include +#include + +//#include "Plugins/Platform/Android/PlatformAndroid.h" +#include "Plugins/Platform/Linux/PlatformLinux.h" +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_hos { + +//class PlatformHOS : public platform_android::PlatformAndroid { +class PlatformHOS : public platform_linux::PlatformLinux { +public: +// PlatformHOS(bool is_host) : PlatformAndroid(is_host) {} + PlatformHOS(bool is_host); + // lldb_private::PluginInterface functions + ~PlatformHOS() override; + static void Initialize(); + + static void Terminate(); + + 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 { + return GetPluginNameStatic(IsHost()); + } + + uint32_t GetPluginVersion() override { return 1; } + + Status ConnectRemote(Args &args) override; + + Status GetFile(const FileSpec &source, const FileSpec &destination) override; + + Status PutFile(const FileSpec &source, const FileSpec &destination, + uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override; + + uint32_t GetSdkVersion(); + + bool GetRemoteOSVersion() override; + + Status DisconnectRemote() override; + + uint32_t GetDefaultMemoryCacheLineSize() override; + +protected: + const char *GetCacheHostname() override; + + Status DownloadModuleSlice(const FileSpec &src_file_spec, + const uint64_t src_offset, const uint64_t src_size, + const FileSpec &dst_file_spec) override; + + Status DownloadSymbolFile(const lldb::ModuleSP &module_sp, + const FileSpec &dst_file_spec) override; + + llvm::StringRef + GetLibdlFunctionDeclarations(lldb_private::Process *process) override; + +private: + HdcClient::SyncService *GetSyncService(Status &error); + + std::unique_ptr m_adb_sync_svc; + std::string m_device_id; + uint32_t m_sdk_version; + +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // liblldb_PlatformHOS_h_ diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp new file mode 100644 index 000000000000..648579c37b1d --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp @@ -0,0 +1,226 @@ +//===-- PlatformHOSRemoteGDBServer.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Host/common/TCPSocket.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UriParser.h" + +#include "PlatformHOSRemoteGDBServer.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::platform_hos; + +static const lldb::pid_t g_remote_platform_pid = + 0; // Alias for the process id of lldb-platform + +static Status ForwardPortWithHdc( + const uint16_t local_port, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + const llvm::Optional &socket_namespace, + std::string &device_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + + HdcClient hdc; + auto error = HdcClient::CreateByDeviceID(device_id, hdc); + if (error.Fail()) + return error; + + device_id = hdc.GetDeviceID(); + LLDB_LOGF(log, "Connected to Hos device \"%s\"", device_id.c_str()); + + if (remote_port != 0) { + LLDB_LOGF(log, "Forwarding remote TCP port %d to local TCP port %d", remote_port, local_port); + return hdc.SetPortForwarding(local_port, remote_port); + } + + LLDB_LOGF(log, "Forwarding remote socket \"%s\" to local TCP port %d", + remote_socket_name.str().c_str(), local_port); + + if (!socket_namespace) + return Status("Invalid socket namespace"); + + return hdc.SetPortForwarding(local_port, remote_socket_name, + *socket_namespace); +} + +static Status DeleteForwardPortWithHdc(uint16_t local_port, + const std::string &device_id) { + HdcClient hdc(device_id); + return hdc.DeletePortForwarding(local_port); +} + +static Status FindUnusedPort(uint16_t &port) { + Status error; + std::unique_ptr tcp_socket(new TCPSocket(true, false)); + if (error.Fail()) + return error; + + error = tcp_socket->Listen("127.0.0.1:0", 1); + if (error.Success()) + port = tcp_socket->GetLocalPortNumber(); + + return error; +} + +PlatformHOSRemoteGDBServer::PlatformHOSRemoteGDBServer() {} + +PlatformHOSRemoteGDBServer::~PlatformHOSRemoteGDBServer() { + for (const auto &it : m_port_forwards) + DeleteForwardPortWithHdc(it.second, m_device_id); +} + +bool PlatformHOSRemoteGDBServer::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)); + + auto error = + MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url); + if (error.Success() && log) + LLDB_LOGF(log, "gdbserver connect URL: %s", connect_url.c_str()); + + return error.Success(); +} + +bool PlatformHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { + DeleteForwardPort(pid); + return m_gdb_client.KillSpawnedProcess(pid); +} + +Status PlatformHOSRemoteGDBServer::ConnectRemote(Args &args) { + m_device_id.clear(); + + if (args.GetArgumentCount() != 1) + return Status( + "\"platform connect\" takes a single argument: "); + + int remote_port; + llvm::StringRef scheme, host, path; + const char *url = args.GetArgumentAtIndex(0); + if (!url) + return Status("URL is null."); + if (!UriParser::Parse(url, scheme, host, remote_port, path)) + return Status("Invalid URL: %s", url); + if (host != "localhost") + m_device_id = std::string(host); + + m_socket_namespace.reset(); + if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME) + m_socket_namespace = HdcClient::UnixSocketNamespaceFileSystem; + else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME) + m_socket_namespace = HdcClient::UnixSocketNamespaceAbstract; + + std::string connect_url; + auto error = + MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port, + path, connect_url); + + if (error.Fail()) + return error; + + args.ReplaceArgumentAtIndex(0, connect_url); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + LLDB_LOGF(log, "Rewritten platform connect URL: %s", connect_url.c_str()); + + error = PlatformRemoteGDBServer::ConnectRemote(args); + if (error.Fail()) + DeleteForwardPort(g_remote_platform_pid); + + return error; +} + +Status PlatformHOSRemoteGDBServer::DisconnectRemote() { + DeleteForwardPort(g_remote_platform_pid); + return PlatformRemoteGDBServer::DisconnectRemote(); +} + +void PlatformHOSRemoteGDBServer::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 = DeleteForwardPortWithHdc(port, m_device_id); + if (error.Fail()) { + LLDB_LOGF(log, + "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); +} + +Status PlatformHOSRemoteGDBServer::MakeConnectURL( + const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, std::string &connect_url) { + static const int kAttempsNum = 5; + + Status error; + // There is a race possibility that somebody will occupy a port while we're + // in between FindUnusedPort and ForwardPortWithHdc - 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 = ForwardPortWithHdc(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://127.0.0.1:" << local_port; + connect_url = url_str.str(); + break; + } + } + + return error; +} + +lldb::ProcessSP PlatformHOSRemoteGDBServer::ConnectProcess( + llvm::StringRef connect_url, llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, lldb_private::Target *target, + lldb_private::Status &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; + llvm::StringRef scheme, host, path; + if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) { + error.SetErrorStringWithFormat("Invalid URL: %s", + connect_url.str().c_str()); + return nullptr; + } + + std::string new_connect_url; + error = MakeConnectURL(s_remote_gdbserver_fake_pid--, + (remote_port < 0) ? 0 : remote_port, path, + new_connect_url); + if (error.Fail()) + return nullptr; + + return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, + debugger, target, error); +} diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h new file mode 100644 index 000000000000..fe27dafcd267 --- /dev/null +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.h @@ -0,0 +1,66 @@ +//===-- PlatformHOSRemoteGDBServer.h ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMHOSREMOTEGDBSERVER_H +#define LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMHOSREMOTEGDBSERVER_H + +#include +#include + +#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h" + +#include "llvm/ADT/Optional.h" + +#include "HdcClient.h" + +namespace lldb_private { +namespace platform_hos { + +class PlatformHOSRemoteGDBServer + : public platform_gdb_server::PlatformRemoteGDBServer { +public: + PlatformHOSRemoteGDBServer(); + + ~PlatformHOSRemoteGDBServer() override; + + Status ConnectRemote(Args &args) override; + + Status DisconnectRemote() override; + + lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url, + llvm::StringRef plugin_name, + lldb_private::Debugger &debugger, + lldb_private::Target *target, + lldb_private::Status &error) override; + +protected: + std::string m_device_id; + std::map m_port_forwards; + llvm::Optional m_socket_namespace; + + bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override; + + bool KillSpawnedProcess(lldb::pid_t pid) override; + + void DeleteForwardPort(lldb::pid_t pid); + + Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port, + llvm::StringRef remote_socket_name, + std::string &connect_url); + +private: + PlatformHOSRemoteGDBServer(const PlatformHOSRemoteGDBServer &) = + delete; + const PlatformHOSRemoteGDBServer & + operator=(const PlatformHOSRemoteGDBServer &) = delete; +}; + +} // namespace platform_hos +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_PLATFORM_HOS_PLATFORMANDROIDREMOTEGDBSERVER_H -- Gitee From e955361e73e800c7f76e25770a6b237e9bd7f465 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 11:59:17 +0000 Subject: [PATCH 03/10] update lldb/source/Interpreter/OptionGroupPlatform.cpp. Signed-off-by: xwx1135370 --- .../Interpreter/OptionGroupPlatform.cpp | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/lldb/source/Interpreter/OptionGroupPlatform.cpp b/lldb/source/Interpreter/OptionGroupPlatform.cpp index 4242e010fa64..d68ac03dc617 100644 --- a/lldb/source/Interpreter/OptionGroupPlatform.cpp +++ b/lldb/source/Interpreter/OptionGroupPlatform.cpp @@ -19,7 +19,10 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions( CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected, Status &error, ArchSpec &platform_arch) const { PlatformSP platform_sp; - + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d OptionGroupPlatform::%s call make_selected:%d", __FILE__, __LINE__, __FUNCTION__, make_selected); + } if (!m_platform_name.empty()) { platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error); if (platform_sp) { @@ -58,6 +61,7 @@ void OptionGroupPlatform::OptionParsingStarting( m_sdk_sysroot.Clear(); m_sdk_build.Clear(); m_os_version = llvm::VersionTuple(); + m_container = false; } static constexpr OptionDefinition g_option_table[] = { @@ -71,6 +75,9 @@ static constexpr OptionDefinition g_option_table[] = { {LLDB_OPT_SET_ALL, false, "build", 'b', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "Specify the initial SDK build number."}, + {LLDB_OPT_SET_ALL, false, "contain", 'c', OptionParser::eRequiredArgument, + nullptr, {}, 0, eArgTypeNone, + "Specifies whether the application is in a container."}, {LLDB_OPT_SET_ALL, false, "sysroot", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Specify the SDK root directory " "that contains a root of all " @@ -92,7 +99,10 @@ OptionGroupPlatform::SetOptionValue(uint32_t option_idx, ++option_idx; const int short_option = g_option_table[option_idx].short_option; - + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d OptionGroupPlatform::%s short_option: %d", __FILE__, __LINE__, __FUNCTION__, short_option); + } switch (short_option) { case 'p': m_platform_name.assign(std::string(option_arg)); @@ -107,6 +117,23 @@ OptionGroupPlatform::SetOptionValue(uint32_t option_idx, case 'b': m_sdk_build.SetString(option_arg); break; + + case 'c': + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d OptionGroupPlatform::%s option_arg:-c %s", __FILE__, __LINE__, __FUNCTION__, option_arg.str().c_str()); + } + + if (std::string(option_arg) == "true") { + m_container = true; + } + else { + m_container = false; + } + + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d OptionGroupPlatform::%s m_container:%d", __FILE__, __LINE__, __FUNCTION__, m_container); + } + break; case 'S': m_sdk_sysroot.SetString(option_arg); @@ -134,6 +161,9 @@ bool OptionGroupPlatform::PlatformMatches( if (!m_os_version.empty() && m_os_version != platform_sp->GetOSVersion()) return false; + + if (m_container != platform_sp->GetContainer()) + return false; return true; } return false; -- Gitee From bb8f054fd79a0aeb040b9586a8d94fe3417cfc56 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:01:04 +0000 Subject: [PATCH 04/10] update lldb/include/lldb/Target/Platform.h. Signed-off-by: xwx1135370 --- lldb/include/lldb/Target/Platform.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index d83f54ca62bc..eb1a40db5316 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -477,6 +477,10 @@ public: void SetSDKBuild(ConstString sdk_build) { m_sdk_build = sdk_build; } + void SetContainer(bool b_container) { m_container = b_container; } + + bool GetContainer() const { return m_container; } + // Override this to return true if your platform supports Clang modules. You // may also need to override AddClangModuleCompilationOptions to pass the // right Clang flags for your platform. @@ -884,6 +888,7 @@ protected: ConstString m_sdk_sysroot; // the root location of where the SDK files are all located ConstString m_sdk_build; + bool m_container; FileSpec m_working_dir; // The working directory which is used when installing // modules that have no install path set std::string m_remote_url; -- Gitee From 873b28b585b1492c9332a8f63db270a3f520e158 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:02:20 +0000 Subject: [PATCH 05/10] update lldb/include/lldb/Interpreter/OptionGroupPlatform.h. Signed-off-by: xwx1135370 --- lldb/include/lldb/Interpreter/OptionGroupPlatform.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lldb/include/lldb/Interpreter/OptionGroupPlatform.h b/lldb/include/lldb/Interpreter/OptionGroupPlatform.h index 99945e5246fd..5e6a59241546 100644 --- a/lldb/include/lldb/Interpreter/OptionGroupPlatform.h +++ b/lldb/include/lldb/Interpreter/OptionGroupPlatform.h @@ -57,6 +57,10 @@ public: ConstString GetSDKBuild() const { return m_sdk_build; } void SetSDKBuild(ConstString sdk_build) { m_sdk_build = sdk_build; } + + bool GetContainer() const { return m_container; } + + void SetContainer(bool b_container) { m_container = b_container; } bool PlatformMatches(const lldb::PlatformSP &platform_sp) const; @@ -64,6 +68,7 @@ protected: std::string m_platform_name; ConstString m_sdk_sysroot; ConstString m_sdk_build; + bool m_container; llvm::VersionTuple m_os_version; bool m_include_platform_option; }; -- Gitee From 51b995dcd9371199df740731c4906cc9c8c8890b Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:04:52 +0000 Subject: [PATCH 06/10] update lldb/source/Target/Platform.cpp. Signed-off-by: xwx1135370 --- lldb/source/Target/Platform.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 8c3c2c013454..86cbfa5fba5e 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -389,7 +389,7 @@ Platform::Platform(bool is_host) m_max_uid_name_len(0), m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(), m_ignores_remote_hostname(false), m_trap_handlers(), - m_calculated_trap_handlers(false), + m_container(false), m_calculated_trap_handlers(false), m_module_cache(std::make_unique()) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); LLDB_LOGF(log, "%p Platform::Platform()", static_cast(this)); @@ -404,8 +404,13 @@ Platform::~Platform() { LLDB_LOGF(log, "%p Platform::~Platform()", static_cast(this)); } +// platform select/connect 返回报文 void Platform::GetStatus(Stream &strm) { std::string s; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) { + LLDB_LOGF(log, "%p Hsu file(%s):%d Platform::GetStatus() call", static_cast(this), __FILE__, __LINE__); + } strm.Printf(" Platform: %s\n", GetPluginName().GetCString()); ArchSpec arch(GetSystemArchitecture()); @@ -431,9 +436,14 @@ void Platform::GetStatus(Stream &strm) { strm.Printf(" Hostname: %s\n", GetHostname()); } else { const bool is_connected = IsConnected(); + const bool is_container = GetContainer(); + if (log) { + LLDB_LOGF(log, "%p Hsu file(%s):%d Platform::GetStatus() is_container(%d) is_connected(%d)", static_cast(this), __FILE__, __LINE__, is_container, is_connected); + } if (is_connected) strm.Printf(" Hostname: %s\n", GetHostname()); strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no"); + strm.Printf(" Container: %s\n", is_container ? "yes" : "no"); } if (GetWorkingDirectory()) { -- Gitee From b96a97a3bed76e87203461924feb986ea735e603 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:05:52 +0000 Subject: [PATCH 07/10] update lldb/source/Target/TargetList.cpp. Signed-off-by: xwx1135370 --- lldb/source/Target/TargetList.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index 1e5856dd0b22..290f52d8fa87 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -62,6 +62,11 @@ Status TargetList::CreateTarget(Debugger &debugger, const ArchSpec &specified_arch, LoadDependentFiles load_dependent_files, PlatformSP &platform_sp, TargetSP &target_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + if (log) { + LLDB_LOGF(log,"Hsu file(%s):%d TargetList::%s call", __FILE__, __LINE__, __FUNCTION__); + } auto result = TargetList::CreateTargetInternal( debugger, user_exe_path, specified_arch, load_dependent_files, platform_sp, target_sp); @@ -76,7 +81,11 @@ Status TargetList::CreateTargetInternal( llvm::StringRef triple_str, LoadDependentFiles load_dependent_files, const OptionGroupPlatform *platform_options, TargetSP &target_sp) { Status error; - + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + if (log) { + LLDB_LOGF(log,"Hsu file(%s):%d TargetList::%s call", __FILE__, __LINE__, __FUNCTION__); + } // Let's start by looking at the selected platform. PlatformSP platform_sp = debugger.GetPlatformList().GetSelectedPlatform(); -- Gitee From 03f681c8707745230ddb5bee38929ebf6a848382 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:06:47 +0000 Subject: [PATCH 08/10] update lldb/source/Plugins/Platform/HOS/HdcClient.cpp. Signed-off-by: xwx1135370 --- .../source/Plugins/Platform/HOS/HdcClient.cpp | 124 +++++++++++++++++- 1 file changed, 117 insertions(+), 7 deletions(-) diff --git a/lldb/source/Plugins/Platform/HOS/HdcClient.cpp b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp index d4e656fcf562..6189a697ed12 100644 --- a/lldb/source/Plugins/Platform/HOS/HdcClient.cpp +++ b/lldb/source/Plugins/Platform/HOS/HdcClient.cpp @@ -23,6 +23,7 @@ #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timeout.h" +#include "lldb/Utility/Log.h" #include @@ -98,7 +99,10 @@ Status HdcClient::CreateByDeviceID(const std::string &device_id, auto error = hdc.GetDevices(connect_devices); if (error.Fail()) return error; - + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s device_id(%s)", __FILE__, __LINE__, __FUNCTION__, device_id.c_str()); + } std::string android_serial; if (!device_id.empty()) android_serial = device_id; @@ -130,11 +134,19 @@ HdcClient::~HdcClient() {} void HdcClient::SetDeviceID(const std::string &device_id) { m_device_id = device_id; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s m_device_id(%s)", __FILE__, __LINE__, __FUNCTION__, m_device_id.c_str()); + } } const std::string &HdcClient::GetDeviceID() const { return m_device_id; } Status HdcClient::Connect() { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s new ConnectionFileDescriptor", __FILE__, __LINE__, __FUNCTION__); + } Status error; m_conn.reset(new ConnectionFileDescriptor); std::string port = "5037"; @@ -144,10 +156,16 @@ Status HdcClient::Connect() { const char *env_port = std::getenv("HDC_SERVER_PORT"); if ((env_port != NULL) && (atoi(env_port) > 0)) { port = env_port; + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s env_port(%s) port(%s)", __FILE__, __LINE__, __FUNCTION__, env_port, port.c_str()); + } } std::string uri = "connect://127.0.0.1:" + port; + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s uri(%s)", __FILE__, __LINE__, __FUNCTION__, uri.c_str()); + } m_conn->Connect(uri.c_str(), &error); return error; @@ -155,6 +173,10 @@ Status HdcClient::Connect() { Status HdcClient::GetDevices(DeviceIDList &device_list) { device_list.clear(); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s call", __FILE__, __LINE__,__FUNCTION__); + } auto error = SendMessage("host:devices"); if (error.Fail()) return error; @@ -181,10 +203,17 @@ Status HdcClient::GetDevices(DeviceIDList &device_list) { Status HdcClient::SetPortForwarding(const uint16_t local_port, const uint16_t remote_port) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d) remote_port(%d)", __FILE__, __LINE__,__FUNCTION__, local_port, remote_port); + } char message[48]; snprintf(message, sizeof(message), "forward:tcp:%d;tcp:%d", local_port, remote_port); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__,__FUNCTION__, message); + } const auto error = SendDeviceMessage(message); if (error.Fail()) return error; @@ -196,6 +225,10 @@ Status HdcClient::SetPortForwarding(const uint16_t local_port, llvm::StringRef remote_socket_name, const UnixSocketNamespace socket_namespace) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d)", __FILE__, __LINE__,__FUNCTION__, local_port); + } char message[PATH_MAX]; const char *sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) @@ -204,6 +237,9 @@ HdcClient::SetPortForwarding(const uint16_t local_port, snprintf(message, sizeof(message), "forward:tcp:%d;%s:%s", local_port, sock_namespace_str, remote_socket_name.str().c_str()); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__,__FUNCTION__, message); + } const auto error = SendDeviceMessage(message); if (error.Fail()) return error; @@ -212,9 +248,16 @@ HdcClient::SetPortForwarding(const uint16_t local_port, } Status HdcClient::DeletePortForwarding(const uint16_t local_port) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s local_port(%d)", __FILE__, __LINE__,__FUNCTION__, local_port); + } char message[32]; snprintf(message, sizeof(message), "killforward:tcp:%d", local_port); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s message(%s)", __FILE__, __LINE__,__FUNCTION__, message); + } const auto error = SendDeviceMessage(message); if (error.Fail()) return error; @@ -224,6 +267,10 @@ Status HdcClient::DeletePortForwarding(const uint16_t local_port) { Status HdcClient::SendMessage(const std::string &packet, const bool reconnect) { Status error; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s packet(%s) reconnect(%d)", __FILE__, __LINE__,__FUNCTION__, packet.c_str(), reconnect); + } if (!m_conn || reconnect) { error = Connect(); if (error.Fail()) @@ -245,14 +292,24 @@ Status HdcClient::SendMessage(const std::string &packet, const bool reconnect) { } Status HdcClient::SendDeviceMessage(const std::string &packet) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s packet(%s) ", __FILE__, __LINE__,__FUNCTION__, packet.c_str()); + } std::ostringstream msg; msg << "host-serial:" << m_device_id << ":" << packet; + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s msg(%s) ", __FILE__, __LINE__,__FUNCTION__, msg.str().c_str()); + } return SendMessage(msg.str()); } Status HdcClient::ReadMessage(std::vector &message) { message.clear(); - + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s call ", __FILE__, __LINE__,__FUNCTION__); + } char buffer[5]; buffer[4] = 0; @@ -275,7 +332,10 @@ Status HdcClient::ReadMessageStream(std::vector &message, milliseconds timeout) { auto start = steady_clock::now(); message.clear(); - + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s call ", __FILE__, __LINE__,__FUNCTION__); + } Status error; lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess; char buffer[1024]; @@ -296,14 +356,17 @@ Status HdcClient::ReadMessageStream(std::vector &message, Status HdcClient::ReadResponseStatus() { char response_id[5]; - + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); static const size_t packet_len = 4; response_id[packet_len] = 0; auto error = ReadAllBytes(response_id, packet_len); if (error.Fail()) return error; - + + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s response_id(%s) ", __FILE__, __LINE__,__FUNCTION__, response_id); + } if (strncmp(response_id, kOKAY, packet_len) != 0) return GetResponseError(response_id); @@ -311,9 +374,12 @@ Status HdcClient::ReadResponseStatus() { } Status HdcClient::GetResponseError(const char *response_id) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (strcmp(response_id, kFAIL) != 0) return Status("Got unexpected response id from hdc: \"%s\"", response_id); - + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s response_id(%s) ", __FILE__, __LINE__,__FUNCTION__, response_id); + } std::vector error_message; auto error = ReadMessage(error_message); if (error.Success()) @@ -325,12 +391,15 @@ Status HdcClient::GetResponseError(const char *response_id) { Status HdcClient::SwitchDeviceTransport() { std::ostringstream msg; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); msg << "host:transport:" << m_device_id; auto error = SendMessage(msg.str()); if (error.Fail()) return error; - + if (log) { + log->Printf("Hsu file(%s):%d HdcClient::%s m_device_id(%s) msg(%s)", __FILE__, __LINE__,__FUNCTION__, m_device_id.c_str(), msg.str().c_str()); + } return ReadResponseStatus(); } @@ -397,6 +466,10 @@ Status HdcClient::internalShell(const char *command, milliseconds timeout, Status HdcClient::Shell(const char *command, milliseconds timeout, std::string *output) { std::vector output_buffer; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s command(%s)", __FILE__, __LINE__, __FUNCTION__, command); + } auto error = internalShell(command, timeout, output_buffer); if (error.Fail()) return error; @@ -409,6 +482,10 @@ Status HdcClient::Shell(const char *command, milliseconds timeout, Status HdcClient::ShellToFile(const char *command, milliseconds timeout, const FileSpec &output_file_spec) { std::vector output_buffer; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s command(%s)", __FILE__, __LINE__, __FUNCTION__, command); + } auto error = internalShell(command, timeout, output_buffer); if (error.Fail()) return error; @@ -416,6 +493,9 @@ Status HdcClient::ShellToFile(const char *command, milliseconds timeout, const auto output_filename = output_file_spec.GetPath(); std::error_code EC; llvm::raw_fd_ostream dst(output_filename, EC, llvm::sys::fs::OF_None); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s output_filename(%s)", __FILE__, __LINE__, __FUNCTION__, output_filename.c_str()); + } if (EC) return Status("Unable to open local file %s", output_filename.c_str()); @@ -443,12 +523,19 @@ Status HdcClient::SyncService::internalPullFile(const FileSpec &remote_file, std::error_code EC; llvm::raw_fd_ostream dst(local_file_path, EC, llvm::sys::fs::OF_None); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s local_file_path(%s)", __FILE__, __LINE__, __FUNCTION__, local_file_path.c_str()); + } if (EC) return Status("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 (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s remote_file_path(%s)", __FILE__, __LINE__, __FUNCTION__, remote_file_path.c_str()); + } if (error.Fail()) return error; @@ -473,6 +560,10 @@ Status HdcClient::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); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s local_file_path(%s)", __FILE__, __LINE__, __FUNCTION__, local_file_path.c_str()); + } if (!src.is_open()) return Status("Unable to open local file %s", local_file_path.c_str()); @@ -481,6 +572,9 @@ Status HdcClient::SyncService::internalPushFile(const FileSpec &local_file, std::string file_description_str = file_description.str(); auto error = SendSyncRequest(kSEND, file_description_str.length(), file_description_str.c_str()); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s file_description_str(%s)", __FILE__, __LINE__, __FUNCTION__, file_description_str.c_str()); + } if (error.Fail()) return error; @@ -524,6 +618,10 @@ Status HdcClient::SyncService::internalStat(const FileSpec &remote_file, const std::string remote_file_path(remote_file.GetPath(false)); auto error = SendSyncRequest(kSTAT, remote_file_path.length(), remote_file_path.c_str()); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s remote_file_path(%s)", __FILE__, __LINE__, __FUNCTION__, remote_file_path.c_str()); + } if (error.Fail()) return Status("Failed to send request: %s", error.AsCString()); @@ -554,6 +652,10 @@ Status HdcClient::SyncService::internalStat(const FileSpec &remote_file, Status HdcClient::SyncService::PullFile(const FileSpec &remote_file, const FileSpec &local_file) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s remote_file(%s) local_file(%s)", __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), local_file.GetPath().c_str()); + } return executeCommand([this, &remote_file, &local_file]() { return internalPullFile(remote_file, local_file); }); @@ -561,6 +663,10 @@ Status HdcClient::SyncService::PullFile(const FileSpec &remote_file, Status HdcClient::SyncService::PushFile(const FileSpec &local_file, const FileSpec &remote_file) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s remote_file(%s) local_file(%s)", __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), local_file.GetPath().c_str()); + } return executeCommand([this, &local_file, &remote_file]() { return internalPushFile(local_file, remote_file); }); @@ -568,6 +674,10 @@ Status HdcClient::SyncService::PushFile(const FileSpec &local_file, Status HdcClient::SyncService::Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d HdcClient::%s remote_file(%s) mode(%d)", __FILE__, __LINE__, __FUNCTION__, remote_file.GetPath().c_str(), mode); + } return executeCommand([this, &remote_file, &mode, &size, &mtime]() { return internalStat(remote_file, mode, size, mtime); }); -- Gitee From 0cdb0ef1a3821ec6d42f90e1a65280ac22cf2d03 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:07:29 +0000 Subject: [PATCH 09/10] update lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp. Signed-off-by: xwx1135370 --- .../Plugins/Platform/HOS/PlatformHOS.cpp | 85 ++++++++++++++++++- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp index c82383ddb897..c6ab5a51f47e 100644 --- a/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOS.cpp @@ -46,11 +46,15 @@ static void platform_setenv(const char *env, const char *val) { void PlatformHOS::Initialize() { PlatformLinux::Initialize(); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (g_initialize_count++ == 0) { #if defined(__HOS__) PlatformSP default_platform_sp(new PlatformHOS(true)); default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); Platform::SetHostPlatform(default_platform_sp); + if (log) { + LLDB_LOGF(log, "Hsu file(%s)%d PlatformHOS::%s new PlatformHOS(true)", __FILE__, __LINE__, __FUNCTION__); + } #endif PluginManager::RegisterPlugin( PlatformHOS::GetPluginNameStatic(false), @@ -111,16 +115,32 @@ PlatformSP PlatformHOS::CreateInstance(bool force, const ArchSpec *arch) { } PlatformHOS::PlatformHOS(bool is_host) - : PlatformLinux(is_host), m_sdk_version(0) {} + : PlatformLinux(is_host), m_sdk_version(0) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + m_container = m_remote_platform_sp->GetContainer(); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d PlatformHOS::%s is_host(%d)",__FILE__, __LINE__, __FUNCTION__, is_host, m_container); + } +} PlatformHOS::~PlatformHOS() {} ConstString PlatformHOS::GetPluginNameStatic(bool is_host) { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu %s:%d PlatformHOS::GetPluginNameStatic is_host(%d)",__FILE__, __LINE__, is_host); + } if (is_host) { static ConstString g_host_name(Platform::GetHostPlatformName()); + if (log) { + LLDB_LOGF(log, "Hsu %s:%d PlatformHOS::GetPluginNameStatic g_host_name",__FILE__, __LINE__); + } return g_host_name; } else { static ConstString g_remote_name("remote-hos"); + if (log) { + LLDB_LOGF(log, "Hsu %s:%d PlatformHOS::GetPluginNameStatic g_remote_name",__FILE__, __LINE__); + } return g_remote_name; } } @@ -133,13 +153,20 @@ const char *PlatformHOS::GetPluginDescriptionStatic(bool is_host) { } Status PlatformHOS::ConnectRemote(Args &args) { m_device_id.clear(); - + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) { + LLDB_LOGF(log, "Hsu %s:%d PlatformHOS::ConnectRemote call",__FILE__, __LINE__); + } + if (IsHost()) { return Status("can't connect to the host platform '%s', always connected", GetPluginName().GetCString()); } if (!m_remote_platform_sp) { + if (log) { + LLDB_LOGF(log, "Hsu %s:%d PlatformHOS::ConnectRemote new PlatformHOSRemoteGDBServer()",__FILE__, __LINE__); + } m_remote_platform_sp = PlatformSP(new PlatformHOSRemoteGDBServer()); } @@ -156,11 +183,17 @@ Status PlatformHOS::ConnectRemote(Args &args) { auto error = PlatformLinux::ConnectRemote(args); if (error.Success()) { HdcClient hdc; + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d PlatformHOS::ConnectRemote m_device_id(%s)",__FILE__, __LINE__, m_device_id.c_str()); + } error = HdcClient::CreateByDeviceID(m_device_id, hdc); if (error.Fail()) return error; m_device_id = hdc.GetDeviceID(); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d PlatformHOS::ConnectRemote m_device_id(%s)",__FILE__, __LINE__, m_device_id.c_str()); + } } return error; } @@ -199,11 +232,57 @@ Status PlatformHOS::GetFile(const FileSpec &source, // mode == 0 can signify that adbd cannot access the file due security // constraints - try "cat ..." as a fallback. + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d PlatformHOS::%s source_file(%s)",__FILE__, __LINE__, __FUNCTION__, source_file); + } HdcClient hdc(m_device_id); char cmd[PATH_MAX]; - snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + int len = strlen(source_file); + std::string tempFile(source_file); + //ÈÝÆ÷ÄÚÆô¶¯µÄÓ¦Óà + if (m_container) { + //ÈÝÆ÷ÄÚ·¾¶Òª×ª»»³ÉÈÝÆ÷ÍâµÄ·¾¶ + /* + ÈÝÆ÷ÄÚ ÈÝÆ÷Íâ + /data /data/ohos_data + /vendor /sytem/ohos/vendor + /system /system/ohos/system + */ + const std::string str_data = "/data"; + const std::string str_vendor = "/vendor"; + const std::string str_system = "/system"; + if (strncmp(source_file, str_data.c_str(), strlen(str_data.c_str()))) { + // ´Ó/dataºóÃæµÄλÖÿªÊ¼½ØÈ¡£¬Ö±µ½×îºó + tempFile.append(tempFile, strlen(str_data.c_str()), len); + tempFile = str_data + tempFile; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + + if (strncmp(source_file, str_vendor.c_str(), strlen(str_vendor.c_str()))) { + tempFile.append(tempFile, strlen(str_vendor.c_str()), len); + tempFile = str_vendor + tempFile; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + + if (strncmp(source_file, str_system.c_str(), strlen(str_system.c_str()))) { + tempFile.append(tempFile, strlen(str_system.c_str()), len); + tempFile = str_system + tempFile; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + return hdc.ShellToFile(cmd, minutes(1), destination); + } + // ÈÝÆ÷ÍâÎÞ¶ÔӦ·¾¶ + return error; + } + else { + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + } + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d PlatformHOS::%s source_file(%s)",__FILE__, __LINE__, __FUNCTION__, source_file); + } return hdc.ShellToFile(cmd, minutes(1), destination); } -- Gitee From 4af5aa8549c2edefd3e86de736a3442100ccb211 Mon Sep 17 00:00:00 2001 From: xwx1135370 Date: Thu, 22 Sep 2022 12:08:05 +0000 Subject: [PATCH 10/10] update lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp. Signed-off-by: xwx1135370 --- .../Platform/HOS/PlatformHOSRemoteGDBServer.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp index 648579c37b1d..fa0f1aeb53e4 100644 --- a/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/HOS/PlatformHOSRemoteGDBServer.cpp @@ -36,10 +36,10 @@ static Status ForwardPortWithHdc( return error; device_id = hdc.GetDeviceID(); - LLDB_LOGF(log, "Connected to Hos device \"%s\"", device_id.c_str()); + LLDB_LOGF(log, "Hsu file(%s):%d function(ForwardPortWithHdc) Connected to Hos device \"%s\"", __FILE__, __LINE__ ,device_id.c_str()); if (remote_port != 0) { - LLDB_LOGF(log, "Forwarding remote TCP port %d to local TCP port %d", remote_port, local_port); + LLDB_LOGF(log, "Hsu file(%s):%d function(ForwardPortWithHdc) Forwarding remote TCP port %d to local TCP port %d",__FILE__, __LINE__, remote_port, local_port); return hdc.SetPortForwarding(local_port, remote_port); } @@ -61,6 +61,7 @@ static Status DeleteForwardPortWithHdc(uint16_t local_port, static Status FindUnusedPort(uint16_t &port) { Status error; + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); std::unique_ptr tcp_socket(new TCPSocket(true, false)); if (error.Fail()) return error; @@ -69,6 +70,9 @@ static Status FindUnusedPort(uint16_t &port) { if (error.Success()) port = tcp_socket->GetLocalPortNumber(); + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d FindUnusedPort port(%d)", __FILE__, __LINE__, port); + } return error; } @@ -103,6 +107,7 @@ bool PlatformHOSRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) { Status PlatformHOSRemoteGDBServer::ConnectRemote(Args &args) { m_device_id.clear(); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (args.GetArgumentCount() != 1) return Status( @@ -128,13 +133,15 @@ Status PlatformHOSRemoteGDBServer::ConnectRemote(Args &args) { auto error = MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port, path, connect_url); - + if (log) { + LLDB_LOGF(log, "Hsu file(%s):%d g_remote_platform_pid(%lu) remote_port(%d) connect_url(%s)", __FILE__, __LINE__, g_remote_platform_pid, remote_port, connect_url.c_str()); + } if (error.Fail()) return error; args.ReplaceArgumentAtIndex(0, connect_url); - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + //Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); LLDB_LOGF(log, "Rewritten platform connect URL: %s", connect_url.c_str()); error = PlatformRemoteGDBServer::ConnectRemote(args); -- Gitee