<rdar://problem/12647273>

Added the ability to get the full process list when using the --applist option in debugserver.

llvm-svn: 167502
This commit is contained in:
Greg Clayton 2012-11-06 23:36:26 +00:00
parent 1c89744f32
commit 9eb4e03873
2 changed files with 169 additions and 60 deletions

View File

@ -40,7 +40,7 @@ typedef std::map<nub_process_t, MachProcessSP> ProcessMap;
typedef ProcessMap::iterator ProcessMapIter;
typedef ProcessMap::const_iterator ProcessMapConstIter;
static size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
static size_t GetAllInfosMatchingName (const char *process_name, std::vector<struct kinfo_proc>& matching_proc_infos);
//----------------------------------------------------------------------
@ -391,10 +391,10 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_
return INVALID_NUB_PROCESS;
}
static size_t
size_t
GetAllInfos (std::vector<struct kinfo_proc>& proc_infos)
{
size_t size;
size_t size = 0;
int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
u_int namelen = sizeof(name)/sizeof(int);
int err;

View File

@ -14,7 +14,11 @@
#import "RNBServices.h"
#import <CoreFoundation/CoreFoundation.h>
#include <libproc.h>
#import <unistd.h>
#include <sys/sysctl.h>
#include "CFString.h"
#include <vector>
#import "DNBLog.h"
#include "MacOSX/CFUtils.h"
@ -22,10 +26,101 @@
#import <SpringBoardServices/SpringBoardServices.h>
#endif
// From DNB.cpp
size_t GetAllInfos (std::vector<struct kinfo_proc>& proc_infos);
int
GetPrcoesses (CFMutableArrayRef plistMutableArray, bool all_users)
{
if (plistMutableArray == NULL)
return -1;
// Running as root, get all processes
std::vector<struct kinfo_proc> proc_infos;
const size_t num_proc_infos = GetAllInfos(proc_infos);
if (num_proc_infos > 0)
{
const pid_t our_pid = getpid();
const uid_t our_uid = getuid();
uint32_t i;
CFAllocatorRef alloc = kCFAllocatorDefault;
for (i=0; i<num_proc_infos; i++)
{
struct kinfo_proc &proc_info = proc_infos[i];
bool kinfo_user_matches;
// Special case, if lldb is being run as root we can attach to anything.
if (all_users)
kinfo_user_matches = true;
else
kinfo_user_matches = proc_info.kp_eproc.e_pcred.p_ruid == our_uid;
const pid_t pid = proc_info.kp_proc.p_pid;
// Skip zombie processes and processes with unset status
if (kinfo_user_matches == false || // User is acceptable
pid == our_pid || // Skip this process
pid == 0 || // Skip kernel (kernel pid is zero)
proc_info.kp_proc.p_stat == SZOMB || // Zombies are bad, they like brains...
proc_info.kp_proc.p_flag & P_TRACED || // Being debugged?
proc_info.kp_proc.p_flag & P_WEXIT || // Working on exiting?
proc_info.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta)
continue;
// Create a new mutable dictionary for each application
CFReleaser<CFMutableDictionaryRef> appInfoDict (::CFDictionaryCreateMutable (alloc, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
// Get the process id for the app (if there is one)
const int32_t pid_int32 = pid;
CFReleaser<CFNumberRef> pidCFNumber (::CFNumberCreate (alloc, kCFNumberSInt32Type, &pid_int32));
::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PID_KEY, pidCFNumber.get());
// Set the a boolean to indicate if this is the front most
::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_FRONTMOST_KEY, kCFBooleanFalse);
const char *pid_basename = proc_info.kp_proc.p_comm;
char proc_path_buf[PATH_MAX];
int return_val = proc_pidpath (pid, proc_path_buf, PATH_MAX);
if (return_val > 0)
{
// Okay, now search backwards from that to see if there is a
// slash in the name. Note, even though we got all the args we don't care
// because the list data is just a bunch of concatenated null terminated strings
// so strrchr will start from the end of argv0.
pid_basename = strrchr(proc_path_buf, '/');
if (pid_basename)
{
// Skip the '/'
++pid_basename;
}
else
{
// We didn't find a directory delimiter in the process argv[0], just use what was in there
pid_basename = proc_path_buf;
}
CFString cf_pid_path (proc_path_buf);
if (cf_pid_path.get())
::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_PATH_KEY, cf_pid_path.get());
}
if (pid_basename && pid_basename[0])
{
CFString pid_name (pid_basename);
::CFDictionarySetValue (appInfoDict.get(), DTSERVICES_APP_DISPLAY_NAME_KEY, pid_name.get());
}
// Append the application info to the plist array
::CFArrayAppendValue (plistMutableArray, appInfoDict.get());
}
}
return 0;
}
int
ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
{
#ifdef WITH_SPRINGBOARD
int result = -1;
CFAllocatorRef alloc = kCFAllocatorDefault;
@ -33,6 +128,18 @@ ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
// Create a mutable array that we can populate. Specify zero so it can be of any size.
CFReleaser<CFMutableArrayRef> plistMutableArray (::CFArrayCreateMutable (alloc, 0, &kCFTypeArrayCallBacks));
const uid_t our_uid = getuid();
#ifdef WITH_SPRINGBOARD
if (our_uid == 0)
{
bool all_users = true;
result = GetPrcoesses (plistMutableArray.get(), all_users);
}
else
{
CFReleaser<CFStringRef> sbsFrontAppID (::SBSCopyFrontmostApplicationDisplayIdentifier ());
CFReleaser<CFArrayRef> sbsAppIDs (::SBSCopyApplicationDisplayIdentifiers (opt_runningApps, opt_debuggable));
@ -82,6 +189,12 @@ ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
// Append the application info to the plist array
::CFArrayAppendValue (plistMutableArray.get(), appInfoDict.get());
}
}
#else
// When root, show all processes
bool all_users = (our_uid == 0);
result = GetPrcoesses (plistMutableArray.get(), all_users);
#endif
CFReleaser<CFDataRef> plistData (::CFPropertyListCreateXMLData (alloc, plistMutableArray.get()));
@ -108,11 +221,7 @@ ListApplications(std::string& plist, bool opt_runningApps, bool opt_debuggable)
}
return result;
#else
// TODO: list all current processes
DNBLogError("SBS doesn't support getting application list.");
return -1;
#endif
}