https://github.com/cs01 updated https://github.com/llvm/llvm-project/pull/160931
>From 617de12c6d9ccfdd89d394c99132c596c9fd07ed Mon Sep 17 00:00:00 2001 From: Chad Smith <[email protected]> Date: Fri, 26 Sep 2025 11:01:19 -0700 Subject: [PATCH 1/2] support attaching by name for platform android --- .../Platform/Android/PlatformAndroid.cpp | 79 +++++++++++++++++++ .../Platform/Android/PlatformAndroid.h | 3 + 2 files changed, 82 insertions(+) diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp index 600cc0a04cd22..bdef98c2d760f 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -477,6 +477,85 @@ std::string PlatformAndroid::GetRunAs() { } return run_as.str(); } +uint32_t +PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos) { + // Use the parent implementation for host platform + if (IsHost()) + return PlatformLinux::FindProcesses(match_info, proc_infos); + + // For remote Android platform, implement process name lookup using adb + proc_infos.clear(); + + // Check if we're looking for a process by name + const ProcessInstanceInfo &match_process_info = match_info.GetProcessInfo(); + if (!match_process_info.GetExecutableFile() || + match_info.GetNameMatchType() == NameMatch::Ignore) { + // Fall back to the parent implementation if not searching by name + return PlatformLinux::FindProcesses(match_info, proc_infos); + } + + std::string process_name = match_process_info.GetExecutableFile().GetPath(); + if (process_name.empty()) + return 0; + + // Use adb to find the process by name + Status error; + AdbClientUP adb(GetAdbClient(error)); + if (error.Fail()) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, "PlatformAndroid::%s failed to get ADB client: %s", + __FUNCTION__, error.AsCString()); + return 0; + } + + // Use 'pidof' command to get the PID for the process name + std::string pidof_output; + std::string command = "pidof " + process_name; + error = adb->Shell(command.c_str(), seconds(5), &pidof_output); + + if (error.Fail()) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, "PlatformAndroid::%s 'pidof %s' failed: %s", __FUNCTION__, + process_name.c_str(), error.AsCString()); + return 0; + } + + // Parse the PID from pidof output + pidof_output = llvm::StringRef(pidof_output).trim().str(); + if (pidof_output.empty()) { + // No process found with that name + return 0; + } + + // Parse the output as a single PID + lldb::pid_t pid; + if (!llvm::to_integer(pidof_output, pid)) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, "PlatformAndroid::%s failed to parse PID from output: '%s'", + __FUNCTION__, pidof_output.c_str()); + return 0; + } + + // Create ProcessInstanceInfo for the found process + ProcessInstanceInfo process_info; + process_info.SetProcessID(pid); + process_info.GetExecutableFile().SetFile(process_name, + FileSpec::Style::posix); + + // Check if this process matches the criteria + if (match_info.Matches(process_info)) { + proc_infos.push_back(process_info); + + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, "PlatformAndroid::%s found process '%s' with PID %llu", + __FUNCTION__, process_name.c_str(), (unsigned long long)pid); + return 1; + } + + return 0; +} + std::unique_ptr<AdbSyncService> PlatformAndroid::GetSyncService(Status &error) { auto sync_service = std::make_unique<AdbSyncService>(m_device_id); error = sync_service->SetupSyncConnection(); diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h index 3384525362ecf..701d12922a383 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h @@ -59,6 +59,9 @@ class PlatformAndroid : public platform_linux::PlatformLinux { uint32_t GetDefaultMemoryCacheLineSize() override; + uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, + ProcessInstanceInfoList &proc_infos) override; + protected: const char *GetCacheHostname() override; >From 41225dd0fd100570799dade9bf8818ac8c30b9bd Mon Sep 17 00:00:00 2001 From: Chad Smith <[email protected]> Date: Wed, 8 Oct 2025 15:45:42 -0700 Subject: [PATCH 2/2] handle edge cases better --- .../Platform/Android/PlatformAndroid.cpp | 90 ++++++++++++------- 1 file changed, 58 insertions(+), 32 deletions(-) diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp index bdef98c2d760f..e14c574bbaefc 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -480,21 +480,30 @@ std::string PlatformAndroid::GetRunAs() { uint32_t PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos) { - // Use the parent implementation for host platform + proc_infos.clear(); + + // When LLDB is running natively on an Android device (IsHost() == true), + // use the parent class's standard Linux /proc enumeration. IsHost() is only + // true when compiled for Android (#if defined(__ANDROID__)), so calling + // PlatformLinux methods is safe (Android is Linux-based). if (IsHost()) return PlatformLinux::FindProcesses(match_info, proc_infos); - // For remote Android platform, implement process name lookup using adb - proc_infos.clear(); + // Remote Android platform: implement process name lookup using 'pidof' over + // adb. - // Check if we're looking for a process by name + // LLDB stores the search name in GetExecutableFile() (even though it's + // actually a process name like "com.android.chrome" rather than an + // executable path). If no search name is provided, we can't use + // 'pidof', so return early with no results. const ProcessInstanceInfo &match_process_info = match_info.GetProcessInfo(); if (!match_process_info.GetExecutableFile() || match_info.GetNameMatchType() == NameMatch::Ignore) { - // Fall back to the parent implementation if not searching by name - return PlatformLinux::FindProcesses(match_info, proc_infos); + return 0; } + // Extract the process name to search for (typically an Android package name + // like "com.example.app" or binary name like "app_process64") std::string process_name = match_process_info.GetExecutableFile().GetPath(); if (process_name.empty()) return 0; @@ -509,10 +518,12 @@ PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info, return 0; } - // Use 'pidof' command to get the PID for the process name + // Use 'pidof' command to get PIDs for the process name. + // Quote the process name to handle special characters (spaces, etc.) std::string pidof_output; - std::string command = "pidof " + process_name; - error = adb->Shell(command.c_str(), seconds(5), &pidof_output); + StreamString command; + command.Printf("pidof '%s'", process_name.c_str()); + error = adb->Shell(command.GetData(), seconds(5), &pidof_output); if (error.Fail()) { Log *log = GetLog(LLDBLog::Platform); @@ -521,39 +532,54 @@ PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info, return 0; } - // Parse the PID from pidof output + // Parse PIDs from pidof output. + // Note: pidof can return multiple PIDs (space-separated) if multiple + // instances of the same executable are running. pidof_output = llvm::StringRef(pidof_output).trim().str(); if (pidof_output.empty()) { - // No process found with that name - return 0; - } - - // Parse the output as a single PID - lldb::pid_t pid; - if (!llvm::to_integer(pidof_output, pid)) { Log *log = GetLog(LLDBLog::Platform); - LLDB_LOGF(log, "PlatformAndroid::%s failed to parse PID from output: '%s'", - __FUNCTION__, pidof_output.c_str()); + LLDB_LOGF(log, "PlatformAndroid::%s no process found with name '%s'", + __FUNCTION__, process_name.c_str()); return 0; } - // Create ProcessInstanceInfo for the found process - ProcessInstanceInfo process_info; - process_info.SetProcessID(pid); - process_info.GetExecutableFile().SetFile(process_name, - FileSpec::Style::posix); + // Split the output by whitespace to handle multiple PIDs + llvm::SmallVector<llvm::StringRef, 8> pid_strings; + llvm::StringRef(pidof_output).split(pid_strings, ' ', -1, false); - // Check if this process matches the criteria - if (match_info.Matches(process_info)) { - proc_infos.push_back(process_info); + uint32_t num_matches = 0; + for (llvm::StringRef pid_str : pid_strings) { + pid_str = pid_str.trim(); + if (pid_str.empty()) + continue; - Log *log = GetLog(LLDBLog::Platform); - LLDB_LOGF(log, "PlatformAndroid::%s found process '%s' with PID %llu", - __FUNCTION__, process_name.c_str(), (unsigned long long)pid); - return 1; + lldb::pid_t pid; + if (!llvm::to_integer(pid_str, pid)) { + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, + "PlatformAndroid::%s failed to parse PID from output: '%s'", + __FUNCTION__, pid_str.str().c_str()); + continue; + } + + // Create ProcessInstanceInfo for the found process + ProcessInstanceInfo process_info; + process_info.SetProcessID(pid); + process_info.GetExecutableFile().SetFile(process_name, + FileSpec::Style::posix); + + // Check if this process matches the criteria + if (match_info.Matches(process_info)) { + proc_infos.push_back(process_info); + num_matches++; + + Log *log = GetLog(LLDBLog::Platform); + LLDB_LOGF(log, "PlatformAndroid::%s found process '%s' with PID %llu", + __FUNCTION__, process_name.c_str(), (unsigned long long)pid); + } } - return 0; + return num_matches; } std::unique_ptr<AdbSyncService> PlatformAndroid::GetSyncService(Status &error) { _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
