@@ -477,24 +477,166 @@ std::string PlatformAndroid::GetRunAs() {
477477 }
478478 return run_as.str ();
479479}
480+
481+ // Helper function to populate process status information from
482+ // /proc/[pid]/status
483+ void PlatformAndroid::PopulateProcessStatusInfo (lldb::pid_t pid,
484+ ProcessInstanceInfo &process_info) {
485+ // Read /proc/[pid]/status to get parent PID, UIDs, and GIDs
486+ Status error;
487+ auto status_adb = GetAdbClient (error);
488+ if (error.Fail ())
489+ return ;
490+
491+ std::string status_output;
492+ StreamString status_cmd;
493+ status_cmd.Printf (
494+ " cat /proc/%llu/status 2>/dev/null | grep -E '^(PPid|Uid|Gid):'" ,
495+ (unsigned long long )pid);
496+ Status status_error =
497+ status_adb->Shell (status_cmd.GetData (), seconds (5 ), &status_output);
498+
499+ if (status_error.Fail () || status_output.empty ())
500+ return ;
501+
502+ llvm::SmallVector<llvm::StringRef, 16 > lines;
503+ llvm::StringRef (status_output).split (lines, ' \n ' );
504+
505+ for (llvm::StringRef line : lines) {
506+ line = line.trim ();
507+ if (line.starts_with (" PPid:" )) {
508+ llvm::StringRef ppid_str = line.substr (5 ).trim ();
509+ lldb::pid_t ppid;
510+ if (llvm::to_integer (ppid_str, ppid))
511+ process_info.SetParentProcessID (ppid);
512+ } else if (line.starts_with (" Uid:" )) {
513+ llvm::SmallVector<llvm::StringRef, 4 > uid_parts;
514+ line.substr (4 ).trim ().split (uid_parts, ' \t ' , -1 , false );
515+ if (uid_parts.size () >= 2 ) {
516+ uint32_t uid, euid;
517+ if (llvm::to_integer (uid_parts[0 ].trim (), uid))
518+ process_info.SetUserID (uid);
519+ if (llvm::to_integer (uid_parts[1 ].trim (), euid))
520+ process_info.SetEffectiveUserID (euid);
521+ }
522+ } else if (line.starts_with (" Gid:" )) {
523+ llvm::SmallVector<llvm::StringRef, 4 > gid_parts;
524+ line.substr (4 ).trim ().split (gid_parts, ' \t ' , -1 , false );
525+ if (gid_parts.size () >= 2 ) {
526+ uint32_t gid, egid;
527+ if (llvm::to_integer (gid_parts[0 ].trim (), gid))
528+ process_info.SetGroupID (gid);
529+ if (llvm::to_integer (gid_parts[1 ].trim (), egid))
530+ process_info.SetEffectiveGroupID (egid);
531+ }
532+ }
533+ }
534+ }
535+
536+ // Helper function to populate command line arguments from /proc/[pid]/cmdline
537+ void PlatformAndroid::PopulateProcessCommandLine (lldb::pid_t pid,
538+ ProcessInstanceInfo &process_info) {
539+ // Read /proc/[pid]/cmdline to get command line arguments
540+ Status error;
541+ auto cmdline_adb = GetAdbClient (error);
542+ if (error.Fail ())
543+ return ;
544+
545+ std::string cmdline_output;
546+ StreamString cmdline_cmd;
547+ cmdline_cmd.Printf (" cat /proc/%llu/cmdline 2>/dev/null | tr '\\ 000' ' '" ,
548+ (unsigned long long )pid);
549+ Status cmdline_error =
550+ cmdline_adb->Shell (cmdline_cmd.GetData (), seconds (5 ), &cmdline_output);
551+
552+ if (cmdline_error.Fail () || cmdline_output.empty ())
553+ return ;
554+
555+ cmdline_output = llvm::StringRef (cmdline_output).trim ().str ();
556+ if (cmdline_output.empty ())
557+ return ;
558+
559+ llvm::SmallVector<llvm::StringRef, 16 > args;
560+ llvm::StringRef (cmdline_output).split (args, ' ' , -1 , false );
561+ if (args.empty ())
562+ return ;
563+
564+ process_info.SetArg0 (args[0 ]);
565+ Args process_args;
566+ for (size_t i = 1 ; i < args.size (); i++) {
567+ if (!args[i].empty ())
568+ process_args.AppendArgument (args[i]);
569+ }
570+ process_info.SetArguments (process_args, false );
571+ }
572+
573+ // Helper function to populate architecture from /proc/[pid]/exe
574+ void PlatformAndroid::PopulateProcessArchitecture (lldb::pid_t pid,
575+ ProcessInstanceInfo &process_info) {
576+ // Read /proc/[pid]/exe to get executable path for architecture detection
577+ Status error;
578+ auto exe_adb = GetAdbClient (error);
579+ if (error.Fail ())
580+ return ;
581+
582+ std::string exe_output;
583+ StreamString exe_cmd;
584+ exe_cmd.Printf (" readlink /proc/%llu/exe 2>/dev/null" ,
585+ (unsigned long long )pid);
586+ Status exe_error = exe_adb->Shell (exe_cmd.GetData (), seconds (5 ), &exe_output);
587+
588+ if (exe_error.Fail () || exe_output.empty ())
589+ return ;
590+
591+ exe_output = llvm::StringRef (exe_output).trim ().str ();
592+
593+ // Determine architecture from exe path
594+ ArchSpec arch;
595+ if (exe_output.find (" 64" ) != std::string::npos ||
596+ exe_output.find (" arm64" ) != std::string::npos ||
597+ exe_output.find (" aarch64" ) != std::string::npos) {
598+ arch.SetTriple (" aarch64-unknown-linux-android" );
599+ } else if (exe_output.find (" x86_64" ) != std::string::npos) {
600+ arch.SetTriple (" x86_64-unknown-linux-android" );
601+ } else if (exe_output.find (" x86" ) != std::string::npos ||
602+ exe_output.find (" i686" ) != std::string::npos) {
603+ arch.SetTriple (" i686-unknown-linux-android" );
604+ } else {
605+ // Default to armv7 for 32-bit ARM (most common on Android)
606+ arch.SetTriple (" armv7-unknown-linux-android" );
607+ }
608+
609+ if (arch.IsValid ())
610+ process_info.SetArchitecture (arch);
611+ }
612+
480613uint32_t
481614PlatformAndroid::FindProcesses (const ProcessInstanceInfoMatch &match_info,
482615 ProcessInstanceInfoList &proc_infos) {
483- // Use the parent implementation for host platform
616+ proc_infos.clear ();
617+
618+ // When LLDB is running natively on an Android device (IsHost() == true),
619+ // use the parent class's standard Linux /proc enumeration. IsHost() is only
620+ // true when compiled for Android (#if defined(__ANDROID__)), so calling
621+ // PlatformLinux methods is safe (Android is Linux-based).
484622 if (IsHost ())
485623 return PlatformLinux::FindProcesses (match_info, proc_infos);
486624
487- // For remote Android platform, implement process name lookup using adb
488- proc_infos. clear ();
625+ // Remote Android platform: implement process name lookup using 'pidof' over
626+ // adb.
489627
490- // Check if we're looking for a process by name
628+ // LLDB stores the search name in GetExecutableFile() (even though it's
629+ // actually a process name like "com.android.chrome" rather than an
630+ // executable path). If no search name is provided, we can't use
631+ // 'pidof', so return early with no results.
491632 const ProcessInstanceInfo &match_process_info = match_info.GetProcessInfo ();
492633 if (!match_process_info.GetExecutableFile () ||
493634 match_info.GetNameMatchType () == NameMatch::Ignore) {
494- // Fall back to the parent implementation if not searching by name
495- return PlatformLinux::FindProcesses (match_info, proc_infos);
635+ return 0 ;
496636 }
497637
638+ // Extract the process name to search for (typically an Android package name
639+ // like "com.example.app" or binary name like "app_process64")
498640 std::string process_name = match_process_info.GetExecutableFile ().GetPath ();
499641 if (process_name.empty ())
500642 return 0 ;
@@ -509,10 +651,12 @@ PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info,
509651 return 0 ;
510652 }
511653
512- // Use 'pidof' command to get the PID for the process name
654+ // Use 'pidof' command to get PIDs for the process name.
655+ // Quote the process name to handle special characters (spaces, etc.)
513656 std::string pidof_output;
514- std::string command = " pidof " + process_name;
515- error = adb->Shell (command.c_str (), seconds (5 ), &pidof_output);
657+ StreamString command;
658+ command.Printf (" pidof '%s'" , process_name.c_str ());
659+ error = adb->Shell (command.GetData (), seconds (5 ), &pidof_output);
516660
517661 if (error.Fail ()) {
518662 Log *log = GetLog (LLDBLog::Platform);
@@ -521,39 +665,58 @@ PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info,
521665 return 0 ;
522666 }
523667
524- // Parse the PID from pidof output
668+ // Parse PIDs from pidof output.
669+ // Note: pidof can return multiple PIDs (space-separated) if multiple
670+ // instances of the same executable are running.
525671 pidof_output = llvm::StringRef (pidof_output).trim ().str ();
526672 if (pidof_output.empty ()) {
527- // No process found with that name
528- return 0 ;
529- }
530-
531- // Parse the output as a single PID
532- lldb::pid_t pid;
533- if (!llvm::to_integer (pidof_output, pid)) {
534673 Log *log = GetLog (LLDBLog::Platform);
535- LLDB_LOGF (log, " PlatformAndroid::%s failed to parse PID from output: '%s'" ,
536- __FUNCTION__, pidof_output .c_str ());
674+ LLDB_LOGF (log, " PlatformAndroid::%s no process found with name '%s'" ,
675+ __FUNCTION__, process_name .c_str ());
537676 return 0 ;
538677 }
539678
540- // Create ProcessInstanceInfo for the found process
541- ProcessInstanceInfo process_info;
542- process_info.SetProcessID (pid);
543- process_info.GetExecutableFile ().SetFile (process_name,
544- FileSpec::Style::posix);
679+ // Split the output by whitespace to handle multiple PIDs
680+ llvm::SmallVector<llvm::StringRef, 8 > pid_strings;
681+ llvm::StringRef (pidof_output).split (pid_strings, ' ' , -1 , false );
545682
546- // Check if this process matches the criteria
547- if (match_info.Matches (process_info)) {
548- proc_infos.push_back (process_info);
683+ Log *log = GetLog (LLDBLog::Platform);
549684
550- Log *log = GetLog (LLDBLog::Platform);
551- LLDB_LOGF (log, " PlatformAndroid::%s found process '%s' with PID %llu" ,
552- __FUNCTION__, process_name.c_str (), (unsigned long long )pid);
553- return 1 ;
685+ // Process each PID and gather information
686+ uint32_t num_matches = 0 ;
687+ for (llvm::StringRef pid_str : pid_strings) {
688+ pid_str = pid_str.trim ();
689+ if (pid_str.empty ())
690+ continue ;
691+
692+ lldb::pid_t pid;
693+ if (!llvm::to_integer (pid_str, pid)) {
694+ LLDB_LOGF (log, " PlatformAndroid::%s failed to parse PID from: '%s'" ,
695+ __FUNCTION__, pid_str.str ().c_str ());
696+ continue ;
697+ }
698+
699+ ProcessInstanceInfo process_info;
700+ process_info.SetProcessID (pid);
701+ process_info.GetExecutableFile ().SetFile (process_name,
702+ FileSpec::Style::posix);
703+
704+ // Populate additional process information
705+ PopulateProcessStatusInfo (pid, process_info);
706+ PopulateProcessCommandLine (pid, process_info);
707+ PopulateProcessArchitecture (pid, process_info);
708+
709+ // Check if this process matches the criteria
710+ if (match_info.Matches (process_info)) {
711+ proc_infos.push_back (process_info);
712+ num_matches++;
713+
714+ LLDB_LOGF (log, " PlatformAndroid::%s found process '%s' with PID %llu" ,
715+ __FUNCTION__, process_name.c_str (), (unsigned long long )pid);
716+ }
554717 }
555718
556- return 0 ;
719+ return num_matches ;
557720}
558721
559722std::unique_ptr<AdbSyncService> PlatformAndroid::GetSyncService (Status &error) {
0 commit comments