diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -38,6 +38,9 @@ lldb_private::Target *target, lldb_private::Status &error) override; + uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) override; + protected: std::string m_device_id; std::map m_port_forwards; diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -9,6 +9,7 @@ #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/common/TCPSocket.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/Status.h" #include "lldb/Utility/UriParser.h" @@ -225,3 +226,117 @@ return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name, debugger, target, error); } + +#define INVALID_INDEX -1 +struct PsColumnsIndices { + int user; + int pid; + int ppid; + int name; + PsColumnsIndices() { user = pid = ppid = name = INVALID_INDEX; } + bool isValid() { return pid != INVALID_INDEX && name != INVALID_INDEX; } +}; + +bool parsePsHeader(const std::string &line, PsColumnsIndices &indices) { + std::stringstream line_stream(line); + std::string column; + for (int columnIndex = 0; line_stream >> column; columnIndex++) { + if (column.empty()) { + continue; + } + if (column == "USER") { + indices.user = columnIndex; + } else if (column == "PID") { + indices.pid = columnIndex; + } else if (column == "PPID") { + indices.ppid = columnIndex; + } else if (column == "NAME") { + indices.name = columnIndex; + } + } + return indices.isValid(); +} + +void parsePsProcessLine(const std::string &line, + const PsColumnsIndices &column_indices, + ProcessInstanceInfo &process_info) { + std::string user, name; + lldb::pid_t pid, ppid; + std::stringstream line_stream(line); + std::string column; + // It is assumed that the name will be the last column because it can + // contain spaces or tab separators + for (int columnIndex = 0; + columnIndex < column_indices.name && line_stream >> column; + columnIndex++) { + if (column.empty()) { + continue; + } + if (column_indices.user == columnIndex) { + user = column; + } else if (column_indices.pid == columnIndex) { + std::stringstream column_stream(column); + column_stream >> pid; + } else if (column_indices.ppid == columnIndex) { + std::stringstream column_stream(column); + column_stream >> ppid; + } + } + std::string name_prefix; + line_stream >> name_prefix; + getline(line_stream, name, '\n'); + name = name + name_prefix; + + process_info.SetProcessID(pid); + process_info.SetParentProcessID(ppid); + process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native); + // TODO: set architecture: process_info.GetArchitecture().SetTriple(...); + // TODO: set user id, we only have the name: process_info.SetUserID(...) +} + +bool findProcessFromCommand(const std::string command, + ProcessInstanceInfoList &process_infos, + AdbClient &adb) { + process_infos.Clear(); + std::string output; + auto status = adb.Shell(command.c_str(), std::chrono::seconds(5), &output); + if (status.Fail()) { + return false; + } + std::stringstream output_stream(output); + std::string line; + getline(output_stream, line, '\n'); + PsColumnsIndices column_indices; + if (!parsePsHeader(line, column_indices)) { + return false; + } + + while (getline(output_stream, line, '\n')) { + ProcessInstanceInfo process_info; + parsePsProcessLine(line, column_indices, process_info); + process_infos.Append(process_info); + } + return true; +} + +bool findProcessesWithAdb(ProcessInstanceInfoList &process_infos, + const std::string device_id) { + AdbClient adb; + auto error = AdbClient::CreateByDeviceID(device_id, adb); + if (error.Fail()) { + return false; + } + + return findProcessFromCommand("ps -A", process_infos, adb) || + findProcessFromCommand("ps", process_infos, adb); +} + +uint32_t PlatformAndroidRemoteGDBServer::FindProcesses( + const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &process_infos) { + if (findProcessesWithAdb(process_infos, m_device_id)) { + return process_infos.GetSize(); + } else { + return PlatformRemoteGDBServer::FindProcesses(match_info, process_infos); + } +} diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -12,8 +12,8 @@ #include -#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" +#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" #include "lldb/Target/Platform.h" namespace lldb_private { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -610,9 +610,9 @@ if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo; - if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", - response, - false) == PacketResult::Success) { + if (SendPacketAndWaitForResponse( + "jGetLoadedDynamicLibrariesInfos:", response, false) == + PacketResult::Success) { if (response.IsOKResponse()) { m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes; } @@ -1124,8 +1124,8 @@ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS)); if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) { - // host info computation can require DNS traffic and shelling out to external processes. - // Increase the timeout to account for that. + // host info computation can require DNS traffic and shelling out to + // external processes. Increase the timeout to account for that. ScopedTimeout timeout(*this, seconds(10)); m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; @@ -1199,10 +1199,9 @@ if (!value.getAsInteger(0, pointer_byte_size)) ++num_keys_decoded; } else if (name.equals("os_version") || - name.equals( - "version")) // Older debugserver binaries used the - // "version" key instead of - // "os_version"... + name.equals("version")) // Older debugserver binaries used + // the "version" key instead of + // "os_version"... { if (!m_os_version.tryParse(value)) ++num_keys_decoded; @@ -2067,7 +2066,7 @@ !vendor_name.empty()) { llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); if (!environment.empty()) - triple.setEnvironmentName(environment); + triple.setEnvironmentName(environment); assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); assert(triple.getObjectFormat() != llvm::Triple::Wasm); @@ -2099,10 +2098,12 @@ } m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name)); - m_process_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); + m_process_arch.GetTriple().setEnvironmentName( + llvm::StringRef(environment)); m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name)); m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name)); - m_host_arch.GetTriple().setEnvironmentName(llvm::StringRef(environment)); + m_host_arch.GetTriple().setEnvironmentName( + llvm::StringRef(environment)); } return true; } @@ -2581,7 +2582,7 @@ * The reply from '?' packet could be as simple as 'S05'. There is no packet * which can * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ + */ if (response.IsUnsupportedResponse() && IsConnected()) { m_curr_tid = 1; return true; @@ -2617,7 +2618,7 @@ * The reply from '?' packet could be as simple as 'S05'. There is no packet * which can * give us pid and/or tid. Assume pid=tid=1 in such cases. - */ + */ if (response.IsUnsupportedResponse() && IsConnected()) { m_curr_tid_run = 1; return true; @@ -2754,7 +2755,7 @@ * be as simple as 'S05'. There is no packet which can give us pid and/or * tid. * Assume pid=tid=1 in such cases. - */ + */ if ((response.IsUnsupportedResponse() || response.IsNormalResponse()) && thread_ids.size() == 0 && IsConnected()) { thread_ids.push_back(1);