]>
Commit | Line | Data |
---|---|---|
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 |
38 | struct prog_configs lsmp_config = { |
39 | .show_all_tasks = FALSE, | |
40 | .show_voucher_details = FALSE, | |
41 | .verbose = FALSE, | |
42 | .pid = 0, | |
43 | }; | |
fc6d9e4b A |
44 | |
45 | my_per_task_info_t *psettaskinfo; | |
46 | mach_msg_type_number_t taskCount; | |
47 | ||
1a7e3f61 A |
48 | static 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 | |
59 | int 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 | } |