]> git.saurik.com Git - apple/system_cmds.git/blob - lsmp.tproj/lsmp.c
4afa36ddc9a9e27344995e398d3daf21180bbccd
[apple/system_cmds.git] / lsmp.tproj / lsmp.c
1 /*
2 * Copyright (c) 2002-20014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 #include <unistd.h>
23 #include <mach/mach.h>
24 #include <mach/mach_error.h>
25 #include <mach_debug/ipc_info.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <libproc.h>
29 #include <TargetConditionals.h>
30 #include "common.h"
31
32
33 #if TARGET_OS_EMBEDDED
34 #define TASK_FOR_PID_USAGE_MESG "\nPlease check your boot-args to ensure you have access to task_for_pid()."
35 #else
36 #define TASK_FOR_PID_USAGE_MESG ""
37 #endif
38
39
40 struct prog_configs lsmp_config = {
41 .show_all_tasks = FALSE,
42 .show_voucher_details = FALSE,
43 .verbose = FALSE,
44 .pid = 0,
45 };
46
47 my_per_task_info_t *psettaskinfo;
48 mach_msg_type_number_t taskCount;
49
50 static void print_usage(char *progname) {
51 fprintf(stderr, "Usage: %s -p <pid> [-a|-v|-h] \n", "lsmp");
52 fprintf(stderr, "Lists information about mach ports. Please see man page for description of each column.\n");
53 fprintf(stderr, "\t-p <pid> : print all mach ports for process id <pid>. \n");
54 fprintf(stderr, "\t-a : print all mach ports for all processeses. \n");
55 fprintf(stderr, "\t-v : print verbose details for kernel objects.\n");
56 fprintf(stderr, "\t-h : print this help.\n");
57 exit(1);
58 }
59
60
61 int main(int argc, char *argv[]) {
62 kern_return_t ret;
63 task_t aTask;
64 my_per_task_info_t *taskinfo = NULL;
65 task_array_t tasks;
66 char *progname = "lsmp";
67 int i, option = 0;
68 lsmp_config.voucher_detail_length = 128; /* default values for config */
69
70 while((option = getopt(argc, argv, "hvalp:")) != -1) {
71 switch(option) {
72 case 'a':
73 /* user asked for info on all processes */
74 lsmp_config.pid = 0;
75 lsmp_config.show_all_tasks = 1;
76 break;
77
78 case 'l':
79 /* for compatibility with sysdiagnose's usage of -all */
80 lsmp_config.voucher_detail_length = 1024;
81 /* Fall through to 'v' */
82
83 case 'v':
84 lsmp_config.show_voucher_details = TRUE;
85 lsmp_config.verbose = TRUE;
86 break;
87
88 case 'p':
89 lsmp_config.pid = atoi(optarg);
90 if (lsmp_config.pid == 0) {
91 fprintf(stderr, "Unknown pid: %s\n", optarg);
92 exit(1);
93 }
94 break;
95
96 default:
97 fprintf(stderr, "Unknown argument. \n");
98 /* Fall through to 'h' */
99
100 case 'h':
101 print_usage(progname);
102 break;
103
104 }
105 }
106 argc -= optind;
107 argv += optind;
108
109
110 /* if privileged, get the info for all tasks so we can match ports up */
111 if (geteuid() == 0) {
112 processor_set_name_array_t psets;
113 mach_msg_type_number_t psetCount;
114 mach_port_t pset_priv;
115
116
117 ret = host_processor_sets(mach_host_self(), &psets, &psetCount);
118 if (ret != KERN_SUCCESS) {
119 fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret));
120 exit(1);
121 }
122 if (psetCount != 1) {
123 fprintf(stderr, "Assertion Failure: pset count greater than one (%d)\n", psetCount);
124 exit(1);
125 }
126
127 /* convert the processor-set-name port to a privileged port */
128 ret = host_processor_set_priv(mach_host_self(), psets[0], &pset_priv);
129 if (ret != KERN_SUCCESS) {
130 fprintf(stderr, "host_processor_set_priv() failed: %s\n", mach_error_string(ret));
131 exit(1);
132 }
133 mach_port_deallocate(mach_task_self(), psets[0]);
134 vm_deallocate(mach_task_self(), (vm_address_t)psets, (vm_size_t)psetCount * sizeof(mach_port_t));
135
136 /* convert the processor-set-priv to a list of tasks for the processor set */
137 ret = processor_set_tasks(pset_priv, &tasks, &taskCount);
138 if (ret != KERN_SUCCESS) {
139 fprintf(stderr, "processor_set_tasks() failed: %s\n", mach_error_string(ret));
140 exit(1);
141 }
142 mach_port_deallocate(mach_task_self(), pset_priv);
143
144 /* swap my current instances port to be last to collect all threads and exception port info */
145 int myTaskPosition = -1;
146 for (int i = 0; i < taskCount; i++) {
147 if (tasks[i] == mach_task_self()){
148 myTaskPosition = i;
149 break;
150 }
151 }
152 if (myTaskPosition >= 0) {
153 mach_port_t swap_holder = MACH_PORT_NULL;
154 swap_holder = tasks[taskCount - 1];
155 tasks[taskCount - 1] = tasks[myTaskPosition];
156 tasks[myTaskPosition] = swap_holder;
157 }
158
159 }
160 else
161 {
162 fprintf(stderr, "warning: should run as root for best output (cross-ref to other tasks' ports).\n");
163 /* just the one process */
164 ret = task_for_pid(mach_task_self(), lsmp_config.pid, &aTask);
165 if (ret != KERN_SUCCESS) {
166 fprintf(stderr, "task_for_pid() failed: %s %s\n", mach_error_string(ret), TASK_FOR_PID_USAGE_MESG);
167 exit(1);
168 }
169 taskCount = 1;
170 tasks = &aTask;
171 }
172
173 /* convert each task to structure of pointer for the task info */
174 psettaskinfo = allocate_taskinfo_memory(taskCount);
175
176 for (i = 0; i < taskCount; i++) {
177 ret = collect_per_task_info(&psettaskinfo[i], tasks[i]);
178 if (ret != KERN_SUCCESS) {
179 printf("Ignoring failure of mach_port_space_info() for task %d for '-all'\n", tasks[i]);
180 continue;
181 }
182
183 if (psettaskinfo[i].pid == lsmp_config.pid)
184 taskinfo = &psettaskinfo[i];
185
186 ret = KERN_SUCCESS;
187 }
188
189
190 if (lsmp_config.show_all_tasks == FALSE) {
191 if (taskinfo == NULL) {
192 fprintf(stderr, "Failed to find task ipc information for pid %d\n", lsmp_config.pid);
193 exit(1);
194 }
195 printf("Process (%d) : %s\n", taskinfo->pid, taskinfo->processName);
196 show_task_mach_ports(taskinfo, taskCount, psettaskinfo);
197 print_task_exception_info(taskinfo);
198 printf("\n");
199 print_task_threads_special_ports(taskinfo);
200
201
202 } else {
203 for (i=0; i < taskCount; i++) {
204 if (psettaskinfo[i].valid != TRUE)
205 continue;
206 printf("Process (%d) : %s\n", psettaskinfo[i].pid, psettaskinfo[i].processName);
207 show_task_mach_ports(&psettaskinfo[i], taskCount, psettaskinfo);
208 print_task_exception_info(&psettaskinfo[i]);
209
210 if (lsmp_config.verbose) {
211 printf("\n");
212 print_task_threads_special_ports(&psettaskinfo[i]);
213 }
214
215 printf("\n\n");
216 }
217 }
218
219 if (taskCount > 1) {
220 vm_deallocate(mach_task_self(), (vm_address_t)tasks, (vm_size_t)taskCount * sizeof(mach_port_t));
221 }
222
223 deallocate_taskinfo_memory(psettaskinfo);
224
225 return(0);
226 }