]> git.saurik.com Git - apple/system_cmds.git/blame - lsmp.tproj/lsmp.c
system_cmds-735.50.6.tar.gz
[apple/system_cmds.git] / lsmp.tproj / lsmp.c
CommitLineData
fc6d9e4b 1/*
cf37c299 2 * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
fc6d9e4b
A
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>
1a7e3f61 30#include "common.h"
fc6d9e4b 31
fc6d9e4b
A
32#if TARGET_OS_EMBEDDED
33#define TASK_FOR_PID_USAGE_MESG "\nPlease check your boot-args to ensure you have access to task_for_pid()."
34#else
35#define TASK_FOR_PID_USAGE_MESG ""
36#endif
fc6d9e4b 37
1a7e3f61
A
38struct prog_configs lsmp_config = {
39 .show_all_tasks = FALSE,
40 .show_voucher_details = FALSE,
41 .verbose = FALSE,
42 .pid = 0,
43};
fc6d9e4b
A
44
45my_per_task_info_t *psettaskinfo;
46mach_msg_type_number_t taskCount;
47
1a7e3f61
A
48static void print_usage(char *progname) {
49 fprintf(stderr, "Usage: %s -p <pid> [-a|-v|-h] \n", "lsmp");
50 fprintf(stderr, "Lists information about mach ports. Please see man page for description of each column.\n");
51 fprintf(stderr, "\t-p <pid> : print all mach ports for process id <pid>. \n");
52 fprintf(stderr, "\t-a : print all mach ports for all processeses. \n");
53 fprintf(stderr, "\t-v : print verbose details for kernel objects.\n");
54 fprintf(stderr, "\t-h : print this help.\n");
55 exit(1);
fc6d9e4b
A
56}
57
fc6d9e4b
A
58
59int main(int argc, char *argv[]) {
1a7e3f61
A
60 kern_return_t ret;
61 task_t aTask;
62 my_per_task_info_t *taskinfo = NULL;
fc6d9e4b 63 task_array_t tasks;
1a7e3f61
A
64 char *progname = "lsmp";
65 int i, option = 0;
66 lsmp_config.voucher_detail_length = 128; /* default values for config */
cf37c299 67
1a7e3f61
A
68 while((option = getopt(argc, argv, "hvalp:")) != -1) {
69 switch(option) {
70 case 'a':
71 /* user asked for info on all processes */
72 lsmp_config.pid = 0;
73 lsmp_config.show_all_tasks = 1;
74 break;
cf37c299 75
1a7e3f61
A
76 case 'l':
77 /* for compatibility with sysdiagnose's usage of -all */
78 lsmp_config.voucher_detail_length = 1024;
79 /* Fall through to 'v' */
cf37c299 80
1a7e3f61
A
81 case 'v':
82 lsmp_config.show_voucher_details = TRUE;
83 lsmp_config.verbose = TRUE;
84 break;
cf37c299 85
1a7e3f61
A
86 case 'p':
87 lsmp_config.pid = atoi(optarg);
88 if (lsmp_config.pid == 0) {
89 fprintf(stderr, "Unknown pid: %s\n", optarg);
90 exit(1);
91 }
92 break;
cf37c299 93
1a7e3f61
A
94 default:
95 fprintf(stderr, "Unknown argument. \n");
96 /* Fall through to 'h' */
cf37c299 97
1a7e3f61
A
98 case 'h':
99 print_usage(progname);
100 break;
cf37c299 101
1a7e3f61
A
102 }
103 }
104 argc -= optind;
105 argv += optind;
cf37c299 106
fc6d9e4b
A
107 /* if privileged, get the info for all tasks so we can match ports up */
108 if (geteuid() == 0) {
109 processor_set_name_array_t psets;
110 mach_msg_type_number_t psetCount;
111 mach_port_t pset_priv;
cf37c299 112
fc6d9e4b
A
113 ret = host_processor_sets(mach_host_self(), &psets, &psetCount);
114 if (ret != KERN_SUCCESS) {
115 fprintf(stderr, "host_processor_sets() failed: %s\n", mach_error_string(ret));
116 exit(1);
117 }
118 if (psetCount != 1) {
119 fprintf(stderr, "Assertion Failure: pset count greater than one (%d)\n", psetCount);
120 exit(1);
121 }
cf37c299 122
fc6d9e4b
A
123 /* convert the processor-set-name port to a privileged port */
124 ret = host_processor_set_priv(mach_host_self(), psets[0], &pset_priv);
125 if (ret != KERN_SUCCESS) {
126 fprintf(stderr, "host_processor_set_priv() failed: %s\n", mach_error_string(ret));
127 exit(1);
128 }
129 mach_port_deallocate(mach_task_self(), psets[0]);
130 vm_deallocate(mach_task_self(), (vm_address_t)psets, (vm_size_t)psetCount * sizeof(mach_port_t));
cf37c299 131
fc6d9e4b
A
132 /* convert the processor-set-priv to a list of tasks for the processor set */
133 ret = processor_set_tasks(pset_priv, &tasks, &taskCount);
134 if (ret != KERN_SUCCESS) {
135 fprintf(stderr, "processor_set_tasks() failed: %s\n", mach_error_string(ret));
136 exit(1);
137 }
138 mach_port_deallocate(mach_task_self(), pset_priv);
cf37c299 139
ac27e6b4
A
140 /* swap my current instances port to be last to collect all threads and exception port info */
141 int myTaskPosition = -1;
142 for (int i = 0; i < taskCount; i++) {
143 if (tasks[i] == mach_task_self()){
144 myTaskPosition = i;
145 break;
146 }
147 }
148 if (myTaskPosition >= 0) {
149 mach_port_t swap_holder = MACH_PORT_NULL;
150 swap_holder = tasks[taskCount - 1];
151 tasks[taskCount - 1] = tasks[myTaskPosition];
152 tasks[myTaskPosition] = swap_holder;
153 }
154
fc6d9e4b
A
155 }
156 else
157 {
158 fprintf(stderr, "warning: should run as root for best output (cross-ref to other tasks' ports).\n");
159 /* just the one process */
1a7e3f61 160 ret = task_for_pid(mach_task_self(), lsmp_config.pid, &aTask);
fc6d9e4b
A
161 if (ret != KERN_SUCCESS) {
162 fprintf(stderr, "task_for_pid() failed: %s %s\n", mach_error_string(ret), TASK_FOR_PID_USAGE_MESG);
163 exit(1);
164 }
1a7e3f61
A
165 taskCount = 1;
166 tasks = &aTask;
fc6d9e4b 167 }
cf37c299 168
1a7e3f61
A
169 /* convert each task to structure of pointer for the task info */
170 psettaskinfo = allocate_taskinfo_memory(taskCount);
cf37c299 171
1a7e3f61
A
172 for (i = 0; i < taskCount; i++) {
173 ret = collect_per_task_info(&psettaskinfo[i], tasks[i]);
174 if (ret != KERN_SUCCESS) {
175 printf("Ignoring failure of mach_port_space_info() for task %d for '-all'\n", tasks[i]);
176 continue;
177 }
cf37c299 178
1a7e3f61
A
179 if (psettaskinfo[i].pid == lsmp_config.pid)
180 taskinfo = &psettaskinfo[i];
cf37c299 181
1a7e3f61
A
182 ret = KERN_SUCCESS;
183 }
cf37c299 184
1a7e3f61
A
185 if (lsmp_config.show_all_tasks == FALSE) {
186 if (taskinfo == NULL) {
187 fprintf(stderr, "Failed to find task ipc information for pid %d\n", lsmp_config.pid);
188 exit(1);
189 }
fc6d9e4b 190 printf("Process (%d) : %s\n", taskinfo->pid, taskinfo->processName);
1a7e3f61
A
191 show_task_mach_ports(taskinfo, taskCount, psettaskinfo);
192 print_task_exception_info(taskinfo);
193 printf("\n");
194 print_task_threads_special_ports(taskinfo);
195
1a7e3f61
A
196 } else {
197 for (i=0; i < taskCount; i++) {
198 if (psettaskinfo[i].valid != TRUE)
fc6d9e4b
A
199 continue;
200 printf("Process (%d) : %s\n", psettaskinfo[i].pid, psettaskinfo[i].processName);
1a7e3f61
A
201 show_task_mach_ports(&psettaskinfo[i], taskCount, psettaskinfo);
202 print_task_exception_info(&psettaskinfo[i]);
203
204 if (lsmp_config.verbose) {
205 printf("\n");
206 print_task_threads_special_ports(&psettaskinfo[i]);
207 }
208
fc6d9e4b
A
209 printf("\n\n");
210 }
211 }
cf37c299 212
1a7e3f61 213 if (taskCount > 1) {
fc6d9e4b 214 vm_deallocate(mach_task_self(), (vm_address_t)tasks, (vm_size_t)taskCount * sizeof(mach_port_t));
fc6d9e4b 215 }
cf37c299 216
1a7e3f61 217 deallocate_taskinfo_memory(psettaskinfo);
cf37c299 218
fc6d9e4b
A
219 return(0);
220}