diff options
Diffstat (limited to 'lldb/tools/darwin-threads/examine-threads.c')
-rw-r--r-- | lldb/tools/darwin-threads/examine-threads.c | 737 |
1 files changed, 365 insertions, 372 deletions
diff --git a/lldb/tools/darwin-threads/examine-threads.c b/lldb/tools/darwin-threads/examine-threads.c index 07212e9..5d96514 100644 --- a/lldb/tools/darwin-threads/examine-threads.c +++ b/lldb/tools/darwin-threads/examine-threads.c @@ -1,291 +1,266 @@ +#include <ctype.h> +#include <dispatch/dispatch.h> +#include <errno.h> +#include <libproc.h> +#include <mach/mach.h> +#include <mach/task_info.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <mach/mach.h> -#include <mach/task_info.h> -#include <time.h> #include <sys/sysctl.h> -#include <ctype.h> -#include <libproc.h> -#include <errno.h> -#include <dispatch/dispatch.h> +#include <time.h> // from System.framework/Versions/B/PrivateHeaders/sys/codesign.h -#define CS_OPS_STATUS 0 /* return status */ -#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ -int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize); +#define CS_OPS_STATUS 0 /* return status */ +#define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */ +int csops(pid_t pid, unsigned int ops, void *useraddr, size_t usersize); /* Step through the process table, find a matching process name, return the pid of that matched process. If there are multiple processes with that name, issue a warning on stdout and return the highest numbered process. The proc_pidpath() call is used which gets the full process name including - directories to the executable and the full (longer than 16 character) + directories to the executable and the full (longer than 16 character) executable name. */ -pid_t -get_pid_for_process_name (const char *procname) -{ - int process_count = proc_listpids (PROC_ALL_PIDS, 0, NULL, 0) / sizeof (pid_t); - if (process_count < 1) - { - printf ("Only found %d processes running!\n", process_count); - exit (1); - } +pid_t get_pid_for_process_name(const char *procname) { + int process_count = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0) / sizeof(pid_t); + if (process_count < 1) { + printf("Only found %d processes running!\n", process_count); + exit(1); + } // Allocate a few extra slots in case new processes are spawned - int all_pids_size = sizeof (pid_t) * (process_count + 3); - pid_t *all_pids = (pid_t *) malloc (all_pids_size); + int all_pids_size = sizeof(pid_t) * (process_count + 3); + pid_t *all_pids = (pid_t *)malloc(all_pids_size); - // re-set process_count in case the number of processes changed (got smaller; we won't do bigger) - process_count = proc_listpids (PROC_ALL_PIDS, 0, all_pids, all_pids_size) / sizeof (pid_t); + // re-set process_count in case the number of processes changed (got smaller; + // we won't do bigger) + process_count = + proc_listpids(PROC_ALL_PIDS, 0, all_pids, all_pids_size) / sizeof(pid_t); int i; pid_t highest_pid = 0; int match_count = 0; - for (i = 1; i < process_count; i++) - { - char pidpath[PATH_MAX]; - int pidpath_len = proc_pidpath (all_pids[i], pidpath, sizeof (pidpath)); - if (pidpath_len == 0) - continue; - char *j = strrchr (pidpath, '/'); - if ((j == NULL && strcmp (procname, pidpath) == 0) - || (j != NULL && strcmp (j + 1, procname) == 0)) - { - match_count++; - if (all_pids[i] > highest_pid) - highest_pid = all_pids[i]; - } + for (i = 1; i < process_count; i++) { + char pidpath[PATH_MAX]; + int pidpath_len = proc_pidpath(all_pids[i], pidpath, sizeof(pidpath)); + if (pidpath_len == 0) + continue; + char *j = strrchr(pidpath, '/'); + if ((j == NULL && strcmp(procname, pidpath) == 0) || + (j != NULL && strcmp(j + 1, procname) == 0)) { + match_count++; + if (all_pids[i] > highest_pid) + highest_pid = all_pids[i]; } - free (all_pids); + } + free(all_pids); - if (match_count == 0) - { - printf ("Did not find process '%s'.\n", procname); - exit (1); - } - if (match_count > 1) - { - printf ("Warning: More than one process '%s'!\n", procname); - printf (" defaulting to the highest-pid one, %d\n", highest_pid); - } + if (match_count == 0) { + printf("Did not find process '%s'.\n", procname); + exit(1); + } + if (match_count > 1) { + printf("Warning: More than one process '%s'!\n", procname); + printf(" defaulting to the highest-pid one, %d\n", highest_pid); + } return highest_pid; } -/* Given a pid, get the full executable name (including directory +/* Given a pid, get the full executable name (including directory paths and the longer-than-16-chars executable name) and return the basename of that (i.e. do not include the directory components). This function mallocs the memory for the string it returns; the caller must free this memory. */ -const char * -get_process_name_for_pid (pid_t pid) -{ +const char *get_process_name_for_pid(pid_t pid) { char tmp_name[PATH_MAX]; - if (proc_pidpath (pid, tmp_name, sizeof (tmp_name)) == 0) - { - printf ("Could not find process with pid of %d\n", (int) pid); - exit (1); - } - if (strrchr (tmp_name, '/')) - return strdup (strrchr (tmp_name, '/') + 1); + if (proc_pidpath(pid, tmp_name, sizeof(tmp_name)) == 0) { + printf("Could not find process with pid of %d\n", (int)pid); + exit(1); + } + if (strrchr(tmp_name, '/')) + return strdup(strrchr(tmp_name, '/') + 1); else - return strdup (tmp_name); + return strdup(tmp_name); } /* Get a struct kinfo_proc structure for a given pid. Process name is required for error printing. - Gives you the current state of the process and whether it is being debugged by anyone. + Gives you the current state of the process and whether it is being debugged + by anyone. memory is malloc()'ed for the returned struct kinfo_proc and must be freed by the caller. */ -struct kinfo_proc * -get_kinfo_proc_for_pid (pid_t pid, const char *process_name) -{ - struct kinfo_proc *kinfo = (struct kinfo_proc *) malloc (sizeof (struct kinfo_proc)); - int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid }; - size_t len = sizeof (struct kinfo_proc); - if (sysctl (mib, sizeof (mib) / sizeof (mib[0]), kinfo, &len, NULL, 0) != 0) - { - free ((void *) kinfo); - printf ("Could not get kinfo_proc for pid %d\n", (int) pid); - exit (1); - } +struct kinfo_proc *get_kinfo_proc_for_pid(pid_t pid, const char *process_name) { + struct kinfo_proc *kinfo = + (struct kinfo_proc *)malloc(sizeof(struct kinfo_proc)); + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + size_t len = sizeof(struct kinfo_proc); + if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), kinfo, &len, NULL, 0) != 0) { + free((void *)kinfo); + printf("Could not get kinfo_proc for pid %d\n", (int)pid); + exit(1); + } return kinfo; } /* Get the basic information (thread_basic_info_t) about a given - thread. - Gives you the suspend count; thread state; user time; system time; sleep time; etc. + thread. + Gives you the suspend count; thread state; user time; system time; sleep + time; etc. The return value is a pointer to malloc'ed memory - it is the caller's responsibility to free it. */ -thread_basic_info_t -get_thread_basic_info (thread_t thread) -{ +thread_basic_info_t get_thread_basic_info(thread_t thread) { kern_return_t kr; - integer_t *thinfo = (integer_t *) malloc (sizeof (integer_t) * THREAD_INFO_MAX); + integer_t *thinfo = (integer_t *)malloc(sizeof(integer_t) * THREAD_INFO_MAX); mach_msg_type_number_t thread_info_count = THREAD_INFO_MAX; - kr = thread_info (thread, THREAD_BASIC_INFO, - (thread_info_t) thinfo, &thread_info_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get basic thread info for a thread\n"); - exit (1); - } - return (thread_basic_info_t) thinfo; + kr = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)thinfo, + &thread_info_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get basic thread info for a thread\n"); + exit(1); + } + return (thread_basic_info_t)thinfo; } -/* Get the thread identifier info (thread_identifier_info_data_t) - about a given thread. - Gives you the system-wide unique thread number; the pthread identifier number +/* Get the thread identifier info (thread_identifier_info_data_t) + about a given thread. + Gives you the system-wide unique thread number; the pthread identifier number */ -thread_identifier_info_data_t -get_thread_identifier_info (thread_t thread) -{ +thread_identifier_info_data_t get_thread_identifier_info(thread_t thread) { kern_return_t kr; thread_identifier_info_data_t tident; mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; - kr = thread_info (thread, THREAD_IDENTIFIER_INFO, - (thread_info_t) &tident, &tident_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get thread ident for a thread\n"); - exit (1); - } + kr = thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&tident, + &tident_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get thread ident for a thread\n"); + exit(1); + } return tident; } - -/* Given a mach port # (in the examine-threads mach port namespace) for a thread, - find the mach port # in the inferior program's port namespace. +/* Given a mach port # (in the examine-threads mach port namespace) for a + thread, + find the mach port # in the inferior program's port namespace. Sets inferior_port if successful. Returns true if successful, false if unable to find the port number. */ -bool -inferior_namespace_mach_port_num (task_t task, thread_t examine_threads_port, thread_t *inferior_port) -{ - kern_return_t retval; - mach_port_name_array_t names; - mach_msg_type_number_t nameslen; - mach_port_type_array_t types; - mach_msg_type_number_t typeslen; - - if (inferior_port == NULL) - return false; - - retval = mach_port_names (task, &names, &nameslen, &types, &typeslen); - if (retval != KERN_SUCCESS) - { - printf ("Error - unable to get mach port names for inferior.\n"); - return false; - } - int i = 0; - for (i = 0; i < nameslen; i++) - { - mach_port_t local_name; - mach_msg_type_name_t local_type; - retval = mach_port_extract_right (task, names[i], MACH_MSG_TYPE_COPY_SEND, &local_name, &local_type); - if (retval == KERN_SUCCESS) - { - mach_port_deallocate (mach_task_self(), local_name); - if (local_name == examine_threads_port) - { - *inferior_port = names[i]; - vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); - vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); - return true; - } - } - } - vm_deallocate (mach_task_self (), (vm_address_t) names, nameslen * sizeof (mach_port_t)); - vm_deallocate (mach_task_self (), (vm_address_t) types, typeslen * sizeof (mach_port_t)); +bool inferior_namespace_mach_port_num(task_t task, + thread_t examine_threads_port, + thread_t *inferior_port) { + kern_return_t retval; + mach_port_name_array_t names; + mach_msg_type_number_t nameslen; + mach_port_type_array_t types; + mach_msg_type_number_t typeslen; + + if (inferior_port == NULL) + return false; + + retval = mach_port_names(task, &names, &nameslen, &types, &typeslen); + if (retval != KERN_SUCCESS) { + printf("Error - unable to get mach port names for inferior.\n"); return false; + } + int i = 0; + for (i = 0; i < nameslen; i++) { + mach_port_t local_name; + mach_msg_type_name_t local_type; + retval = mach_port_extract_right(task, names[i], MACH_MSG_TYPE_COPY_SEND, + &local_name, &local_type); + if (retval == KERN_SUCCESS) { + mach_port_deallocate(mach_task_self(), local_name); + if (local_name == examine_threads_port) { + *inferior_port = names[i]; + vm_deallocate(mach_task_self(), (vm_address_t)names, + nameslen * sizeof(mach_port_t)); + vm_deallocate(mach_task_self(), (vm_address_t)types, + typeslen * sizeof(mach_port_t)); + return true; + } + } + } + vm_deallocate(mach_task_self(), (vm_address_t)names, + nameslen * sizeof(mach_port_t)); + vm_deallocate(mach_task_self(), (vm_address_t)types, + typeslen * sizeof(mach_port_t)); + return false; } /* Get the current pc value for a given thread. */ -uint64_t -get_current_pc (thread_t thread, int *wordsize) -{ - kern_return_t kr ; +uint64_t get_current_pc(thread_t thread, int *wordsize) { + kern_return_t kr; -#if defined (__x86_64__) || defined (__i386__) +#if defined(__x86_64__) || defined(__i386__) x86_thread_state_t gp_regs; mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; - kr = thread_get_state (thread, x86_THREAD_STATE, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, x86_THREAD_STATE, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } - if (gp_regs.tsh.flavor == x86_THREAD_STATE64) - { - *wordsize = 8; - return gp_regs.uts.ts64.__rip; - } - else - { - *wordsize = 4; - return gp_regs.uts.ts32.__eip; - } + if (gp_regs.tsh.flavor == x86_THREAD_STATE64) { + *wordsize = 8; + return gp_regs.uts.ts64.__rip; + } else { + *wordsize = 4; + return gp_regs.uts.ts32.__eip; + } #endif -#if defined (__arm__) +#if defined(__arm__) arm_thread_state_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE_COUNT; - kr = thread_get_state (thread, ARM_THREAD_STATE, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, ARM_THREAD_STATE, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } *wordsize = 4; return gp_regs.__pc; #endif -#if defined (__arm64__) +#if defined(__arm64__) arm_thread_state64_t gp_regs; mach_msg_type_number_t gp_count = ARM_THREAD_STATE64_COUNT; - kr = thread_get_state (thread, ARM_THREAD_STATE64, - (thread_state_t) &gp_regs, &gp_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get registers for a thread\n"); - exit (1); - } + kr = thread_get_state(thread, ARM_THREAD_STATE64, (thread_state_t)&gp_regs, + &gp_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get registers for a thread\n"); + exit(1); + } *wordsize = 8; return gp_regs.__pc; #endif - } /* Get the proc_threadinfo for a given thread. - Gives you the thread name, if set; current and max priorities. + Gives you the thread name, if set; current and max priorities. Returns 1 if successful Returns 0 if proc_pidinfo() failed */ -int -get_proc_threadinfo (pid_t pid, uint64_t thread_handle, struct proc_threadinfo *pth) -{ +int get_proc_threadinfo(pid_t pid, uint64_t thread_handle, + struct proc_threadinfo *pth) { pth->pth_name[0] = '\0'; - int ret = proc_pidinfo (pid, PROC_PIDTHREADINFO, thread_handle, - pth, sizeof (struct proc_threadinfo)); + int ret = proc_pidinfo(pid, PROC_PIDTHREADINFO, thread_handle, pth, + sizeof(struct proc_threadinfo)); if (ret != 0) return 1; else return 0; } -int -main (int argc, char **argv) -{ +int main(int argc, char **argv) { kern_return_t kr; task_t task; pid_t pid = 0; @@ -294,221 +269,239 @@ main (int argc, char **argv) int do_loop = 0; int verbose = 0; int resume_when_done = 0; - mach_port_t mytask = mach_task_self (); + mach_port_t mytask = mach_task_self(); - if (argc != 2 && argc != 3 && argc != 4 && argc != 5) - { - printf ("Usage: tdump [-l] [-v] [-r] pid/procname\n"); - exit (1); - } - - if (argc == 3 || argc == 4) - { - int i = 1; - while (i < argc - 1) - { - if (strcmp (argv[i], "-l") == 0) - do_loop = 1; - if (strcmp (argv[i], "-v") == 0) - verbose = 1; - if (strcmp (argv[i], "-r") == 0) - resume_when_done++; - i++; - } + if (argc != 2 && argc != 3 && argc != 4 && argc != 5) { + printf("Usage: tdump [-l] [-v] [-r] pid/procname\n"); + exit(1); + } + + if (argc == 3 || argc == 4) { + int i = 1; + while (i < argc - 1) { + if (strcmp(argv[i], "-l") == 0) + do_loop = 1; + if (strcmp(argv[i], "-v") == 0) + verbose = 1; + if (strcmp(argv[i], "-r") == 0) + resume_when_done++; + i++; } + } char *c = argv[argc - 1]; - if (*c == '\0') - { - printf ("Usage: tdump [-l] [-v] pid/procname\n"); - exit (1); - } - while (*c != '\0') - { - if (!isdigit (*c)) - { - arg_is_procname = 1; - procname = argv[argc - 1]; - break; - } - c++; + if (*c == '\0') { + printf("Usage: tdump [-l] [-v] pid/procname\n"); + exit(1); + } + while (*c != '\0') { + if (!isdigit(*c)) { + arg_is_procname = 1; + procname = argv[argc - 1]; + break; } + c++; + } - if (arg_is_procname && procname) - { - pid = get_pid_for_process_name (procname); - } - else - { - errno = 0; - pid = (pid_t) strtol (argv[argc - 1], NULL, 10); - if (pid == 0 && errno == EINVAL) - { - printf ("Usage: tdump [-l] [-v] pid/procname\n"); - exit (1); - } + if (arg_is_procname && procname) { + pid = get_pid_for_process_name(procname); + } else { + errno = 0; + pid = (pid_t)strtol(argv[argc - 1], NULL, 10); + if (pid == 0 && errno == EINVAL) { + printf("Usage: tdump [-l] [-v] pid/procname\n"); + exit(1); } + } - const char *process_name = get_process_name_for_pid (pid); + const char *process_name = get_process_name_for_pid(pid); - // At this point "pid" is the process id and "process_name" is the process name - // Now we have to get the process list from the kernel (which only has the truncated + // At this point "pid" is the process id and "process_name" is the process + // name + // Now we have to get the process list from the kernel (which only has the + // truncated // 16 char names) - struct kinfo_proc *kinfo = get_kinfo_proc_for_pid (pid, process_name); + struct kinfo_proc *kinfo = get_kinfo_proc_for_pid(pid, process_name); - printf ("pid %d (%s) is currently ", pid, process_name); + printf("pid %d (%s) is currently ", pid, process_name); switch (kinfo->kp_proc.p_stat) { - case SIDL: printf ("being created by fork"); break; - case SRUN: printf ("runnable"); break; - case SSLEEP: printf ("sleeping on an address"); break; - case SSTOP: printf ("suspended"); break; - case SZOMB: printf ("zombie state - awaiting collection by parent"); break; - default: printf ("unknown"); + case SIDL: + printf("being created by fork"); + break; + case SRUN: + printf("runnable"); + break; + case SSLEEP: + printf("sleeping on an address"); + break; + case SSTOP: + printf("suspended"); + break; + case SZOMB: + printf("zombie state - awaiting collection by parent"); + break; + default: + printf("unknown"); } if (kinfo->kp_proc.p_flag & P_TRACED) - printf (" and is being debugged."); - free ((void *) kinfo); + printf(" and is being debugged."); + free((void *)kinfo); - printf ("\n"); + printf("\n"); int csops_flags = 0; - if (csops (pid, CS_OPS_STATUS, &csops_flags, sizeof (csops_flags)) != -1 - && (csops_flags & CS_RESTRICT)) - { - printf ("pid %d (%s) is restricted so nothing can attach to it.\n", pid, process_name); + if (csops(pid, CS_OPS_STATUS, &csops_flags, sizeof(csops_flags)) != -1 && + (csops_flags & CS_RESTRICT)) { + printf("pid %d (%s) is restricted so nothing can attach to it.\n", pid, + process_name); } - kr = task_for_pid (mach_task_self (), pid, &task); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to task_for_pid()\n"); - exit (1); - } + kr = task_for_pid(mach_task_self(), pid, &task); + if (kr != KERN_SUCCESS) { + printf("Error - unable to task_for_pid()\n"); + exit(1); + } struct task_basic_info info; unsigned int info_count = TASK_BASIC_INFO_COUNT; - kr = task_info (task, TASK_BASIC_INFO, (task_info_t) &info, &info_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to call task_info.\n"); - exit (1); - } - printf ("Task suspend count: %d.\n", info.suspend_count); + kr = task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &info_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to call task_info.\n"); + exit(1); + } + printf("Task suspend count: %d.\n", info.suspend_count); - struct timespec *rqtp = (struct timespec *) malloc (sizeof (struct timespec)); + struct timespec *rqtp = (struct timespec *)malloc(sizeof(struct timespec)); rqtp->tv_sec = 0; rqtp->tv_nsec = 150000000; int loop_cnt = 1; - do - { - int i; - if (do_loop) - printf ("Iteration %d:\n", loop_cnt++); - thread_array_t thread_list; - mach_msg_type_number_t thread_count; - - kr = task_threads (task, &thread_list, &thread_count); - if (kr != KERN_SUCCESS) - { - printf ("Error - unable to get thread list\n"); - exit (1); + do { + int i; + if (do_loop) + printf("Iteration %d:\n", loop_cnt++); + thread_array_t thread_list; + mach_msg_type_number_t thread_count; + + kr = task_threads(task, &thread_list, &thread_count); + if (kr != KERN_SUCCESS) { + printf("Error - unable to get thread list\n"); + exit(1); + } + printf("pid %d has %d threads\n", pid, thread_count); + if (verbose) + printf("\n"); + + for (i = 0; i < thread_count; i++) { + thread_basic_info_t basic_info = get_thread_basic_info(thread_list[i]); + + thread_identifier_info_data_t identifier_info = + get_thread_identifier_info(thread_list[i]); + + int wordsize; + uint64_t pc = get_current_pc(thread_list[i], &wordsize); + + printf("thread #%d, system-wide-unique-tid %lld, suspend count is %d, ", + i, identifier_info.thread_id, basic_info->suspend_count); + if (wordsize == 8) + printf("pc 0x%016llx, ", pc); + else + printf("pc 0x%08llx, ", pc); + printf("run state is "); + switch (basic_info->run_state) { + case TH_STATE_RUNNING: + puts("running"); + break; + case TH_STATE_STOPPED: + puts("stopped"); + break; + case TH_STATE_WAITING: + puts("waiting"); + break; + case TH_STATE_UNINTERRUPTIBLE: + puts("uninterruptible"); + break; + case TH_STATE_HALTED: + puts("halted"); + break; + default: + puts(""); + } + + printf(" pthread handle id 0x%llx (not the same value as " + "pthread_self() returns)\n", + (uint64_t)identifier_info.thread_handle); + + struct proc_threadinfo pth; + int proc_threadinfo_succeeded = + get_proc_threadinfo(pid, identifier_info.thread_handle, &pth); + + if (proc_threadinfo_succeeded && pth.pth_name[0] != '\0') + printf(" thread name '%s'\n", pth.pth_name); + + printf(" libdispatch qaddr 0x%llx (not the same as the " + "dispatch_queue_t token)\n", + (uint64_t)identifier_info.dispatch_qaddr); + + if (verbose) { + printf( + " (examine-threads port namespace) mach port # 0x%4.4x\n", + (int)thread_list[i]); + thread_t mach_port_inferior_namespace; + if (inferior_namespace_mach_port_num(task, thread_list[i], + &mach_port_inferior_namespace)) + printf(" (inferior port namepsace) mach port # 0x%4.4x\n", + (int)mach_port_inferior_namespace); + printf(" user %d.%06ds, system %d.%06ds", + basic_info->user_time.seconds, + basic_info->user_time.microseconds, + basic_info->system_time.seconds, + basic_info->system_time.microseconds); + if (basic_info->cpu_usage > 0) { + float cpu_percentage = basic_info->cpu_usage / 10.0; + printf(", using %.1f%% cpu currently", cpu_percentage); } - printf ("pid %d has %d threads\n", pid, thread_count); - if (verbose) - printf ("\n"); - - for (i = 0; i < thread_count; i++) - { - thread_basic_info_t basic_info = get_thread_basic_info (thread_list[i]); - - thread_identifier_info_data_t identifier_info = get_thread_identifier_info (thread_list[i]); - - int wordsize; - uint64_t pc = get_current_pc (thread_list[i], &wordsize); - - printf ("thread #%d, system-wide-unique-tid %lld, suspend count is %d, ", i, - identifier_info.thread_id, - basic_info->suspend_count); - if (wordsize == 8) - printf ("pc 0x%016llx, ", pc); - else - printf ("pc 0x%08llx, ", pc); - printf ("run state is "); - switch (basic_info->run_state) { - case TH_STATE_RUNNING: puts ("running"); break; - case TH_STATE_STOPPED: puts ("stopped"); break; - case TH_STATE_WAITING: puts ("waiting"); break; - case TH_STATE_UNINTERRUPTIBLE: puts ("uninterruptible"); break; - case TH_STATE_HALTED: puts ("halted"); break; - default: puts (""); - } - - printf (" pthread handle id 0x%llx (not the same value as pthread_self() returns)\n", (uint64_t) identifier_info.thread_handle); - - struct proc_threadinfo pth; - int proc_threadinfo_succeeded = get_proc_threadinfo (pid, identifier_info.thread_handle, &pth); - - if (proc_threadinfo_succeeded && pth.pth_name[0] != '\0') - printf (" thread name '%s'\n", pth.pth_name); - - printf (" libdispatch qaddr 0x%llx (not the same as the dispatch_queue_t token)\n", (uint64_t) identifier_info.dispatch_qaddr); - - if (verbose) - { - printf (" (examine-threads port namespace) mach port # 0x%4.4x\n", (int) thread_list[i]); - thread_t mach_port_inferior_namespace; - if (inferior_namespace_mach_port_num (task, thread_list[i], &mach_port_inferior_namespace)) - printf (" (inferior port namepsace) mach port # 0x%4.4x\n", (int) mach_port_inferior_namespace); - printf (" user %d.%06ds, system %d.%06ds", - basic_info->user_time.seconds, basic_info->user_time.microseconds, - basic_info->system_time.seconds, basic_info->system_time.microseconds); - if (basic_info->cpu_usage > 0) - { - float cpu_percentage = basic_info->cpu_usage / 10.0; - printf (", using %.1f%% cpu currently", cpu_percentage); - } - if (basic_info->sleep_time > 0) - printf (", this thread has slept for %d seconds", basic_info->sleep_time); - - printf ("\n "); - printf ("scheduling policy %d", basic_info->policy); - - if (basic_info->flags != 0) - { - printf (", flags %d", basic_info->flags); - if ((basic_info->flags | TH_FLAGS_SWAPPED) == TH_FLAGS_SWAPPED) - printf (" (thread is swapped out)"); - if ((basic_info->flags | TH_FLAGS_IDLE) == TH_FLAGS_IDLE) - printf (" (thread is idle)"); - } - if (proc_threadinfo_succeeded) - printf (", current pri %d, max pri %d", pth.pth_curpri, pth.pth_maxpriority); - - printf ("\n\n"); - } - - free ((void *) basic_info); + if (basic_info->sleep_time > 0) + printf(", this thread has slept for %d seconds", + basic_info->sleep_time); + + printf("\n "); + printf("scheduling policy %d", basic_info->policy); + + if (basic_info->flags != 0) { + printf(", flags %d", basic_info->flags); + if ((basic_info->flags | TH_FLAGS_SWAPPED) == TH_FLAGS_SWAPPED) + printf(" (thread is swapped out)"); + if ((basic_info->flags | TH_FLAGS_IDLE) == TH_FLAGS_IDLE) + printf(" (thread is idle)"); } - if (do_loop) - printf ("\n"); - vm_deallocate (mytask, (vm_address_t) thread_list, - thread_count * sizeof (thread_act_t)); - nanosleep (rqtp, NULL); - } while (do_loop); - - while (resume_when_done > 0) - { - kern_return_t err = task_resume (task); - if (err != KERN_SUCCESS) - printf ("Error resuming task: %d.", err); - resume_when_done--; + if (proc_threadinfo_succeeded) + printf(", current pri %d, max pri %d", pth.pth_curpri, + pth.pth_maxpriority); + + printf("\n\n"); + } + + free((void *)basic_info); } + if (do_loop) + printf("\n"); + vm_deallocate(mytask, (vm_address_t)thread_list, + thread_count * sizeof(thread_act_t)); + nanosleep(rqtp, NULL); + } while (do_loop); + + while (resume_when_done > 0) { + kern_return_t err = task_resume(task); + if (err != KERN_SUCCESS) + printf("Error resuming task: %d.", err); + resume_when_done--; + } - vm_deallocate (mytask, (vm_address_t) task, sizeof (task_t)); - free ((void *) process_name); + vm_deallocate(mytask, (vm_address_t)task, sizeof(task_t)); + free((void *)process_name); return 0; } |