[Lldb-commits] [lldb] support attaching by name for platform android (PR #160931)
Chad Smith via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 8 15:49:54 PDT 2025
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 <cssmith at meta.com>
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 0ddd9a5bbcdbbe5e7a2c2fefb45092c3ce2a83ec Mon Sep 17 00:00:00 2001
From: Chad Smith <cssmith at fb.com>
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..68206a5a70421 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) {
More information about the lldb-commits
mailing list