]> git.saurik.com Git - apple/system_cmds.git/blob - lsmp.tproj/port_details.c
de852463dacb2fbae5bbe941accd37bff2bf417a
[apple/system_cmds.git] / lsmp.tproj / port_details.c
1 /*
2 * Copyright (c) 2002-2016 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
23 #include <stdio.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <libproc.h>
27 #include <assert.h>
28 #include <mach/mach.h>
29 //#include <mach/mach_port.h.h>
30 #include <mach/mach_voucher.h>
31 #include "common.h"
32 #include "json.h"
33
34 const char * kobject_name(natural_t kotype)
35 {
36 switch (kotype) {
37 case IKOT_NONE: return "message-queue";
38 case IKOT_THREAD: return "THREAD";
39 case IKOT_TASK: return "TASK";
40 case IKOT_HOST: return "HOST";
41 case IKOT_HOST_PRIV: return "HOST-PRIV";
42 case IKOT_PROCESSOR: return "PROCESSOR";
43 case IKOT_PSET: return "PROCESSOR-SET";
44 case IKOT_PSET_NAME: return "PROCESSOR-SET-NAME";
45 case IKOT_TIMER: return "TIMER";
46 case IKOT_PAGING_REQUEST: return "PAGER-REQUEST";
47 case IKOT_MIG: return "MIG";
48 case IKOT_MEMORY_OBJECT: return "MEMORY-OBJECT";
49 case IKOT_XMM_PAGER: return "XMM-PAGER";
50 case IKOT_XMM_KERNEL: return "XMM-KERNEL";
51 case IKOT_XMM_REPLY: return "XMM-REPLY";
52 case IKOT_UND_REPLY: return "UND-REPLY";
53 case IKOT_HOST_NOTIFY: return "message-queue";
54 case IKOT_HOST_SECURITY: return "HOST-SECURITY";
55 case IKOT_LEDGER: return "LEDGER";
56 case IKOT_MASTER_DEVICE: return "MASTER-DEVICE";
57 case IKOT_TASK_NAME: return "TASK-NAME";
58 case IKOT_SUBSYSTEM: return "SUBSYSTEM";
59 case IKOT_IO_DONE_QUEUE: return "IO-QUEUE-DONE";
60 case IKOT_SEMAPHORE: return "SEMAPHORE";
61 case IKOT_LOCK_SET: return "LOCK-SET";
62 case IKOT_CLOCK: return "CLOCK";
63 case IKOT_CLOCK_CTRL: return "CLOCK-CONTROL";
64 case IKOT_IOKIT_IDENT: return "IOKIT-IDENT";
65 case IKOT_NAMED_ENTRY: return "NAMED-MEMORY";
66 case IKOT_IOKIT_CONNECT: return "IOKIT-CONNECT";
67 case IKOT_IOKIT_OBJECT: return "IOKIT-OBJECT";
68 case IKOT_UPL: return "UPL";
69 case IKOT_MEM_OBJ_CONTROL: return "XMM-CONTROL";
70 case IKOT_AU_SESSIONPORT: return "SESSIONPORT";
71 case IKOT_FILEPORT: return "FILEPORT";
72 case IKOT_LABELH: return "MACF-LABEL";
73 case IKOT_TASK_RESUME: return "TASK_RESUME";
74 case IKOT_VOUCHER: return "VOUCHER";
75 case IKOT_VOUCHER_ATTR_CONTROL: return "VOUCHER_ATTR_CONTROL";
76 case IKOT_WORK_INTERVAL: return "WORK_INTERVAL";
77 case IKOT_UX_HANDLER: return "UX_HANDLER";
78 case IKOT_UEXT_OBJECT: return "UEXT_OBJECT";
79 case IKOT_ARCADE_REG: return "ARCADE_REG";
80 case IKOT_UNKNOWN:
81 default: return "UNKNOWN";
82 }
83 }
84
85 const port_status_flag_info_t port_status_flags[] = {
86 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TEMPOWNER)] = {
87 .flag = MACH_PORT_STATUS_FLAG_TEMPOWNER,
88 .compact_name = "T",
89 .name = "tempowner",
90 },
91 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_GUARDED)] = {
92 .flag = MACH_PORT_STATUS_FLAG_GUARDED,
93 .compact_name = "G",
94 .name = "guarded",
95 },
96 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_STRICT_GUARD)] = {
97 .flag = MACH_PORT_STATUS_FLAG_STRICT_GUARD,
98 .compact_name = "S",
99 .name = "strict guard",
100 },
101 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_IMP_DONATION)] = {
102 .flag = MACH_PORT_STATUS_FLAG_IMP_DONATION,
103 .compact_name = "I",
104 .name = "imp donation",
105 },
106 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_REVIVE)] = {
107 .flag = MACH_PORT_STATUS_FLAG_REVIVE,
108 .compact_name = "R",
109 .name = "revive",
110 },
111 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TASKPTR)] = {
112 .flag = MACH_PORT_STATUS_FLAG_TASKPTR,
113 .compact_name = "P",
114 .name = "taskptr",
115 },
116 {0},
117 };
118
119 #define VOUCHER_DETAIL_PREFIX " "
120
121 static const unsigned int voucher_contents_size = 8192;
122 static uint8_t voucher_contents[voucher_contents_size];
123
124 typedef struct {
125 int total;
126 int sendcount;
127 int receivecount;
128 int sendoncecount;
129 int portsetcount;
130 int deadcount;
131 int dncount;
132 int vouchercount;
133 } task_table_entry_counts;
134
135 typedef task_table_entry_counts * task_table_entry_counts_t;
136
137 static void show_task_table_entry(ipc_info_name_t *entry, my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos, task_table_entry_counts_t counts, JSON_t json);
138
139 static uint32_t safesize (int len){
140 return (len > 0) ? len : 0;
141 }
142
143 uint32_t show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, uint32_t maxlen, JSON_t json) {
144 JSON_OBJECT_BEGIN(json);
145
146 uint32_t len = 0;
147 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "Key: %u, ", recipe->key);
148 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Command: %u, ", recipe->command);
149 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Previous voucher: 0x%x, ", recipe->previous_voucher);
150 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Content size: %u\n", recipe->content_size);
151
152 JSON_OBJECT_SET(json, key, %u, recipe->key);
153 JSON_OBJECT_SET(json, command, %u, recipe->command);
154 JSON_OBJECT_SET(json, previous_voucher, "0x%x", recipe->previous_voucher);
155 JSON_OBJECT_SET(json, content_size, %u, recipe->content_size);
156
157 switch (recipe->key) {
158 case MACH_VOUCHER_ATTR_KEY_ATM:
159 JSON_OBJECT_SET(json, ATM_ID, %llu, *(uint64_t *)(uintptr_t)recipe->content);
160 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "ATM ID: %llu", *(uint64_t *)(uintptr_t)recipe->content);
161 break;
162 case MACH_VOUCHER_ATTR_KEY_IMPORTANCE:
163 // content may not be valid JSON, exclude
164 // JSON_OBJECT_SET(json, importance_info, "%s", (char *)recipe->content);
165 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "IMPORTANCE INFO: %s", (char *)recipe->content);
166 break;
167 case MACH_VOUCHER_ATTR_KEY_BANK:
168 // content may not be valid JSON, exclude
169 // JSON_OBJECT_SET(json, resource_accounting_info, "%s", (char *)recipe->content);
170 len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "RESOURCE ACCOUNTING INFO: %s", (char *)recipe->content);
171 break;
172 default:
173 len += print_hex_data(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX, "Recipe Contents", (void *)recipe->content, MIN(recipe->content_size, lsmp_config.voucher_detail_length));
174 break;
175 }
176
177 if (len + 1 < maxlen && voucher_outstr[len - 1] != '\n') {
178 voucher_outstr[len++] = '\n';
179 voucher_outstr[len] = '\0';
180 }
181 JSON_OBJECT_END(json); // recipe
182 return len;
183 }
184
185
186 char * copy_voucher_detail(mach_port_t task, mach_port_name_t voucher, JSON_t json) {
187 unsigned int recipe_size = voucher_contents_size;
188 kern_return_t kr = KERN_SUCCESS;
189 bzero((void *)&voucher_contents[0], sizeof(voucher_contents));
190 unsigned v_kobject = 0;
191 unsigned v_kotype = 0;
192 uint32_t detail_maxlen = VOUCHER_DETAIL_MAXLEN;
193 char * voucher_outstr = (char *)malloc(detail_maxlen);
194 voucher_outstr[0] = '\0';
195 uint32_t plen = 0;
196
197 kr = mach_port_kernel_object( task,
198 voucher,
199 &v_kotype, (unsigned *)&v_kobject);
200 if (kr == KERN_SUCCESS && v_kotype == IKOT_VOUCHER ) {
201
202 kr = mach_voucher_debug_info(task, voucher,
203 (mach_voucher_attr_raw_recipe_array_t)&voucher_contents[0],
204 &recipe_size);
205 if (kr != KERN_SUCCESS && kr != KERN_NOT_SUPPORTED) {
206 plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Voucher: 0x%x Failed to get contents %s\n", v_kobject, mach_error_string(kr));
207 return voucher_outstr;
208 }
209
210 if (recipe_size == 0) {
211 plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Voucher: 0x%x has no contents\n", v_kobject);
212 return voucher_outstr;
213 }
214
215 plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Voucher: 0x%x\n", v_kobject);
216 unsigned int used_size = 0;
217 mach_voucher_attr_recipe_t recipe = NULL;
218 while (recipe_size > used_size) {
219 recipe = (mach_voucher_attr_recipe_t)&voucher_contents[used_size];
220 if (recipe->key) {
221 plen += show_recipe_detail(recipe, &voucher_outstr[plen], safesize(detail_maxlen - plen), json);
222 }
223 used_size += sizeof(mach_voucher_attr_recipe_data_t) + recipe->content_size;
224 }
225 } else {
226 plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Invalid voucher: 0x%x\n", voucher);
227 }
228
229 return voucher_outstr;
230 }
231
232 void get_receive_port_context(task_t taskp, mach_port_name_t portname, mach_port_context_t *context) {
233 if (context == NULL) {
234 return;
235 }
236
237 kern_return_t ret;
238 ret = mach_port_get_context(taskp, portname, context);
239 if (ret != KERN_SUCCESS) {
240 fprintf(stderr, "mach_port_get_context(0x%08x) failed: %s\n",
241 portname,
242 mach_error_string(ret));
243 *context = (mach_port_context_t)0;
244 }
245 return;
246 }
247
248 int get_recieve_port_status(task_t taskp, mach_port_name_t portname, mach_port_info_ext_t *info){
249 if (info == NULL) {
250 return -1;
251 }
252 mach_msg_type_number_t statusCnt;
253 kern_return_t ret;
254 statusCnt = MACH_PORT_INFO_EXT_COUNT;
255 ret = mach_port_get_attributes(taskp,
256 portname,
257 MACH_PORT_INFO_EXT,
258 (mach_port_info_t)info,
259 &statusCnt);
260 if (ret != KERN_SUCCESS) {
261 fprintf(stderr, "mach_port_get_attributes(0x%08x) failed: %s\n",
262 portname,
263 mach_error_string(ret));
264 return -1;
265 }
266
267 return 0;
268 }
269
270 void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos, JSON_t json)
271 {
272 int i;
273 task_table_entry_counts counts = {0};
274
275 counts.total = taskinfo->tableCount + taskinfo->treeCount;
276
277 JSON_KEY(json, ports)
278 JSON_ARRAY_BEGIN(json);
279
280 printf(" name ipc-object rights flags boost reqs recv send sonce oref qlimit msgcount context identifier type\n");
281 printf("--------- ---------- ---------- -------- ----- ---- ----- ----- ----- ---- ------ -------- ------------------ ----------- ------------\n");
282 for (i = 0; i < taskinfo->tableCount; i++) {
283 show_task_table_entry(&taskinfo->table[i], taskinfo, taskCount, allTaskInfos, &counts, json);
284 }
285
286 JSON_ARRAY_END(json); // ports
287 JSON_OBJECT_SET(json, total, %d, counts.total);
288 JSON_OBJECT_SET(json, send_rights, %d, counts.sendcount);
289 JSON_OBJECT_SET(json, receive_rights, %d, counts.receivecount);
290 JSON_OBJECT_SET(json, send_once_rights, %d, counts.sendoncecount);
291 JSON_OBJECT_SET(json, port_sets, %d, counts.portsetcount);
292 JSON_OBJECT_SET(json, dead_names, %d, counts.deadcount);
293 JSON_OBJECT_SET(json, dead_name requests, %d, counts.dncount);
294 JSON_OBJECT_SET(json, vouchers, %d, counts.vouchercount);
295
296 printf("\n");
297 printf("total = %d\n", counts.total);
298 printf("SEND = %d\n", counts.sendcount);
299 printf("RECEIVE = %d\n", counts.receivecount);
300 printf("SEND_ONCE = %d\n", counts.sendoncecount);
301 printf("PORT_SET = %d\n", counts.portsetcount);
302 printf("DEAD_NAME = %d\n", counts.deadcount);
303 printf("DNREQUEST = %d\n", counts.dncount);
304 printf("VOUCHERS = %d\n", counts.vouchercount);
305 }
306
307 static void show_task_table_entry(ipc_info_name_t *entry, my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos, task_table_entry_counts_t counts, JSON_t json) {
308 int j, k, port_status_flag_idx;
309 kern_return_t ret;
310 boolean_t send = FALSE;
311 boolean_t dnreq = FALSE;
312 int sendrights = 0;
313 unsigned int kotype = 0;
314 vm_offset_t kobject = (vm_offset_t)0;
315 kobject_description_t desc;
316 mach_vm_address_t kaddr;
317
318 /* skip empty slots in the table */
319 if ((entry->iin_type & MACH_PORT_TYPE_ALL_RIGHTS) == 0) {
320 counts->total--;
321 return;
322 }
323
324 if (entry->iin_type == MACH_PORT_TYPE_PORT_SET) {
325 mach_port_name_array_t members;
326 mach_msg_type_number_t membersCnt;
327
328 ret = mach_port_get_set_status(taskinfo->task,
329 entry->iin_name,
330 &members, &membersCnt);
331 if (ret != KERN_SUCCESS) {
332 fprintf(stderr, "mach_port_get_set_status(0x%08x) failed: %s\n",
333 entry->iin_name,
334 mach_error_string(ret));
335 return;
336 }
337
338 JSON_OBJECT_BEGIN(json);
339 JSON_OBJECT_SET(json, type, "port set");
340 JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name);
341 JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object);
342
343 JSON_KEY(json, members);
344 JSON_ARRAY_BEGIN(json);
345
346 printf("0x%08x 0x%08x port-set -------- --- 1 %d members\n",
347 entry->iin_name,
348 entry->iin_object,
349 membersCnt);
350 /* get some info for each portset member */
351 for (j = 0; j < membersCnt; j++) {
352 for (k = 0; k < taskinfo->tableCount; k++) {
353 if (taskinfo->table[k].iin_name == members[j]) {
354 mach_port_info_ext_t info;
355 mach_port_status_t port_status;
356 mach_port_context_t port_context = (mach_port_context_t)0;
357 if (0 != get_recieve_port_status(taskinfo->task, taskinfo->table[k].iin_name, &info)) {
358 bzero((void *)&info, sizeof(info));
359 }
360 port_status = info.mpie_status;
361 get_receive_port_context(taskinfo->task, taskinfo->table[k].iin_name, &port_context);
362
363 JSON_OBJECT_BEGIN(json);
364 JSON_OBJECT_SET(json, ipc-object, "0x%08x", taskinfo->table[k].iin_object);
365
366 JSON_KEY(json, rights);
367 JSON_ARRAY_BEGIN(json);
368 JSON_ARRAY_APPEND(json, "recv");
369 if (taskinfo->table[k].iin_type & MACH_PORT_TYPE_SEND) {
370 JSON_ARRAY_APPEND(json, "send");
371 }
372 JSON_ARRAY_END(json); // rights
373
374 JSON_KEY(json, port_status_flags);
375 JSON_ARRAY_BEGIN(json);
376 port_status_flag_idx = 0;
377 while (0 != port_status_flags[port_status_flag_idx++].flag) {
378 if (port_status.mps_flags & INDEX_TO_PORT_FLAG(port_status_flag_idx)) {
379 JSON_ARRAY_APPEND(json, "%s", port_status_flags[port_status_flag_idx].name);
380 }
381 }
382 JSON_ARRAY_END(json); // port status flags
383 JSON_OBJECT_SET(json, boosts, %d, info.mpie_boost_cnt);
384
385 JSON_KEY(json, notifications);
386 JSON_ARRAY_BEGIN(json);
387 if (taskinfo->table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) {
388 JSON_ARRAY_APPEND(json, "dead name");
389 }
390 if (port_status.mps_nsrequest) {
391 JSON_ARRAY_APPEND(json, "no sender");
392 }
393 if (port_status.mps_nsrequest) {
394 JSON_ARRAY_APPEND(json, "port destroy request");
395 }
396 JSON_ARRAY_END(json); // notifications
397
398 JSON_OBJECT_SET(json, recv_rights, %d, 1);
399 JSON_OBJECT_SET(json, send_rights, %d, taskinfo->table[k].iin_urefs);
400 JSON_OBJECT_SET(json, send_once_rights, %d, port_status.mps_sorights);
401 JSON_OBJECT_SET_BOOL(json, oref, port_status.mps_srights);
402 JSON_OBJECT_SET(json, queue_limit, %d, port_status.mps_qlimit);
403 JSON_OBJECT_SET(json, msg_count, %d, port_status.mps_msgcount);
404 JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)port_context);
405 JSON_OBJECT_SET(json, identifier, "0x%08x", taskinfo->table[k].iin_name);
406 JSON_OBJECT_SET(json, pid, %d, taskinfo->pid);
407 JSON_OBJECT_SET(json, process, "%s", taskinfo->processName);
408 JSON_OBJECT_END(json); // member
409
410 printf(" - 0x%08x %s --%s%s%s%s%s%s %5d %s%s%s %5d %5.0d %5.0d %s %6d %8d 0x%016llx 0x%08x (%d) %s\n",
411 taskinfo->table[k].iin_object,
412 (taskinfo->table[k].iin_type & MACH_PORT_TYPE_SEND) ? "recv,send ":"recv ",
413 SHOW_PORT_STATUS_FLAGS(port_status.mps_flags),
414 info.mpie_boost_cnt,
415 (taskinfo->table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-",
416 (port_status.mps_nsrequest) ? "N" : "-",
417 (port_status.mps_pdrequest) ? "P" : "-",
418 1,
419 taskinfo->table[k].iin_urefs,
420 port_status.mps_sorights,
421 (port_status.mps_srights) ? "Y" : "N",
422 port_status.mps_qlimit,
423 port_status.mps_msgcount,
424 (uint64_t)port_context,
425 taskinfo->table[k].iin_name,
426 taskinfo->pid,
427 taskinfo->processName);
428 break;
429 }
430 }
431 }
432
433 JSON_ARRAY_END(json); // members
434 JSON_OBJECT_END(json); // port-set
435
436 ret = vm_deallocate(mach_task_self(), (vm_address_t)members,
437 membersCnt * sizeof(mach_port_name_t));
438 if (ret != KERN_SUCCESS) {
439 fprintf(stderr, "vm_deallocate() failed: %s\n",
440 mach_error_string(ret));
441 exit(1);
442 }
443 counts->portsetcount++;
444 return;
445 }
446
447 if (entry->iin_type & MACH_PORT_TYPE_SEND) {
448 send = TRUE;
449 sendrights = entry->iin_urefs;
450 counts->sendcount++;
451 }
452
453 if (entry->iin_type & MACH_PORT_TYPE_DNREQUEST) {
454 dnreq = TRUE;
455 counts->dncount++;
456 }
457
458 if (entry->iin_type & MACH_PORT_TYPE_RECEIVE) {
459 mach_port_status_t status;
460 mach_port_info_ext_t info;
461 mach_port_context_t context = (mach_port_context_t)0;
462 struct k2n_table_node *k2nnode;
463 ret = get_recieve_port_status(taskinfo->task, entry->iin_name, &info);
464 get_receive_port_context(taskinfo->task, entry->iin_name, &context);
465 /* its ok to fail in fetching attributes */
466 if (ret < 0) {
467 return;
468 }
469 status = info.mpie_status;
470
471 JSON_OBJECT_BEGIN(json);
472 JSON_OBJECT_SET(json, type, "port");
473 JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name);
474 JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object);
475
476 JSON_KEY(json, rights);
477 JSON_ARRAY_BEGIN(json);
478 JSON_ARRAY_APPEND(json, "recv");
479 if (send) JSON_ARRAY_APPEND(json, "send");
480 JSON_ARRAY_END(json); // rights
481
482 JSON_KEY(json, port_status_flags);
483 JSON_ARRAY_BEGIN(json);
484 port_status_flag_idx = 0;
485 while (0 != port_status_flags[port_status_flag_idx++].flag) {
486 if (status.mps_flags & INDEX_TO_PORT_FLAG(port_status_flag_idx)) {
487 JSON_ARRAY_APPEND(json, "%s", port_status_flags[port_status_flag_idx].name);
488 }
489 }
490 JSON_ARRAY_END(json); // port status flags
491 JSON_OBJECT_SET(json, boosts, %d, info.mpie_boost_cnt);
492
493 JSON_KEY(json, notifications);
494 JSON_ARRAY_BEGIN(json);
495 if (dnreq) {
496 JSON_ARRAY_APPEND(json, "dead name");
497 }
498 if (status.mps_nsrequest) {
499 JSON_ARRAY_APPEND(json, "no sender");
500 }
501 if (status.mps_nsrequest) {
502 JSON_ARRAY_APPEND(json, "port destroy request");
503 }
504 JSON_ARRAY_END(json); // notifications
505
506 JSON_OBJECT_SET(json, recv_rights, %d, 1);
507 JSON_OBJECT_SET(json, send_rights, %d, sendrights);
508 JSON_OBJECT_SET(json, send_once_rights, %d, status.mps_sorights);
509 JSON_OBJECT_SET_BOOL(json, oref, status.mps_srights);
510 JSON_OBJECT_SET(json, queue_limit, %d, status.mps_qlimit);
511 JSON_OBJECT_SET(json, msg_count, %d, status.mps_msgcount);
512 JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)context);
513 JSON_OBJECT_END(json); // port
514
515 printf("0x%08x 0x%08x %s --%s%s%s%s%s%s %5d %s%s%s %5d %5.0d %5.0d %s %6d %8d 0x%016llx \n",
516 entry->iin_name,
517 entry->iin_object,
518 (send) ? "recv,send ":"recv ",
519 SHOW_PORT_STATUS_FLAGS(status.mps_flags),
520 info.mpie_boost_cnt,
521 (dnreq) ? "D":"-",
522 (status.mps_nsrequest) ? "N":"-",
523 (status.mps_pdrequest) ? "P":"-",
524 1,
525 sendrights,
526 status.mps_sorights,
527 (status.mps_srights) ? "Y":"N",
528 status.mps_qlimit,
529 status.mps_msgcount,
530 (uint64_t)context);
531 counts->receivecount++;
532
533 /* show other rights (in this and other tasks) for the port */
534 for (j = 0; j < taskCount; j++) {
535 if (allTaskInfos[j].valid == FALSE)
536 continue;
537
538 k2nnode = k2n_table_lookup(allTaskInfos[j].k2ntable, entry->iin_object);
539
540 while (k2nnode) {
541 if (k2nnode->info_name != entry) {
542 assert(k2nnode->info_name->iin_object == entry->iin_object);
543
544 printf(" + %s -------- %s%s%s %5d <- 0x%08x (%d) %s\n",
545 (k2nnode->info_name->iin_type & MACH_PORT_TYPE_SEND_ONCE) ?
546 "send-once " : "send ",
547 (k2nnode->info_name->iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-",
548 "-",
549 "-",
550 k2nnode->info_name->iin_urefs,
551 k2nnode->info_name->iin_name,
552 allTaskInfos[j].pid,
553 allTaskInfos[j].processName);
554 }
555
556 k2nnode = k2n_table_lookup_next(k2nnode, entry->iin_object);
557 }
558 }
559 return;
560 }
561 else if (entry->iin_type & MACH_PORT_TYPE_DEAD_NAME)
562 {
563 JSON_OBJECT_BEGIN(json);
564 JSON_OBJECT_SET(json, type, "dead name");
565 JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name);
566 JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object);
567 JSON_OBJECT_SET(json, send_rights, %d, entry->iin_urefs);
568 JSON_OBJECT_END(json); // dead name
569
570 printf("0x%08x 0x%08x dead-name -------- --- %5d \n",
571 entry->iin_name,
572 entry->iin_object,
573 entry->iin_urefs);
574 counts->deadcount++;
575 return;
576 }
577
578 if (entry->iin_type & MACH_PORT_TYPE_SEND_ONCE) {
579 counts->sendoncecount++;
580 }
581
582 JSON_OBJECT_BEGIN(json);
583 JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name);
584 JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object);
585
586 JSON_KEY(json, rights);
587 JSON_ARRAY_BEGIN(json);
588 JSON_ARRAY_APPEND(json, "%s", (send) ? "send":"send once");
589 JSON_ARRAY_END(json); //rights
590
591 JSON_KEY(json, notifications);
592 JSON_ARRAY_BEGIN(json);
593 if (dnreq) JSON_ARRAY_APPEND(json, "dead name");
594 JSON_ARRAY_END(json); // notifications
595
596 JSON_OBJECT_SET(json, send_rights, %d, (send) ? sendrights : 0);
597
598 printf("0x%08x 0x%08x %s -------- %s%s%s %5.0d ",
599 entry->iin_name,
600 entry->iin_object,
601 (send) ? "send ":"send-once ",
602 (dnreq) ? "D":"-",
603 "-",
604 "-",
605 (send) ? sendrights : 0);
606
607 /* converting to kobjects is not always supported */
608
609 desc[0] = '\0';
610 ret = mach_port_kobject_description(taskinfo->task,
611 entry->iin_name,
612 &kotype, &kaddr,
613 desc);
614 if (KERN_SUCCESS == ret) {
615 kobject = (unsigned) kaddr;
616 } else {
617 ret = mach_port_kernel_object(taskinfo->task,
618 entry->iin_name,
619 &kotype, (unsigned *)&kobject);
620 }
621
622 if (ret == KERN_SUCCESS && kotype != 0) {
623 JSON_OBJECT_SET(json, identifier, "0x%08x", (natural_t)kobject);
624 JSON_OBJECT_SET(json, type, "%s", kobject_name(kotype));
625 if (desc[0]) {
626 JSON_OBJECT_SET(json, description, "%s", desc);
627 printf(" 0x%08x %s %s", (natural_t)kobject, kobject_name(kotype), desc);
628 } else {
629 printf(" 0x%08x %s", (natural_t)kobject, kobject_name(kotype));
630 }
631 if ((kotype == IKOT_TASK_RESUME) || (kotype == IKOT_TASK) || (kotype == IKOT_TASK_NAME)) {
632 if (taskinfo->task_kobject == kobject) {
633 /* neat little optimization since in most cases tasks have themselves in their ipc space */
634 JSON_OBJECT_SET(json, pid, %d, taskinfo->pid);
635 JSON_OBJECT_SET(json, process, "%s", taskinfo->processName);
636 printf(" SELF (%d) %s", taskinfo->pid, taskinfo->processName);
637 } else {
638 my_per_task_info_t * _found_task = get_taskinfo_by_kobject((natural_t)kobject);
639 JSON_OBJECT_SET(json, pid, %d, _found_task->pid);
640 JSON_OBJECT_SET(json, process, "%s", _found_task->processName);
641 printf(" (%d) %s", _found_task->pid, _found_task->processName);
642 }
643 }
644
645 if (kotype == IKOT_THREAD) {
646 for (int i = 0; i < taskinfo->threadCount; i++) {
647 if (taskinfo->threadInfos[i].th_kobject == kobject) {
648 printf(" (%#llx)", taskinfo->threadInfos[i].th_id);
649 break;
650 }
651 }
652 }
653
654 printf("\n");
655 if (kotype == IKOT_VOUCHER) {
656 counts->vouchercount++;
657 if (lsmp_config.show_voucher_details) {
658 JSON_KEY(json, recipes);
659 JSON_ARRAY_BEGIN(json);
660 char * detail = copy_voucher_detail(taskinfo->task, entry->iin_name, json);
661 JSON_ARRAY_END(json); // recipes
662 printf("%s\n", detail);
663 free(detail);
664 }
665 }
666 JSON_OBJECT_END(json); // kobject
667 return;
668 }
669
670 /* not kobject - find the receive right holder */
671 my_per_task_info_t *recv_holder_taskinfo;
672 mach_port_name_t recv_name = MACH_PORT_NULL;
673 if (KERN_SUCCESS == get_taskinfo_of_receiver_by_send_right(entry, &recv_holder_taskinfo, &recv_name)) {
674 mach_port_status_t port_status;
675 mach_port_info_ext_t info;
676 mach_port_context_t port_context = (mach_port_context_t)0;
677 if (0 != get_recieve_port_status(recv_holder_taskinfo->task, recv_name, &info)) {
678 bzero((void *)&port_status, sizeof(port_status));
679 }
680 port_status = info.mpie_status;
681 get_receive_port_context(recv_holder_taskinfo->task, recv_name, &port_context);
682
683 JSON_OBJECT_SET(json, queue_limit, %d, port_status.mps_qlimit);
684 JSON_OBJECT_SET(json, msg_count, %d, port_status.mps_msgcount);
685 JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)port_context);
686 JSON_OBJECT_SET(json, identifier, "0x%08x", recv_name);
687 JSON_OBJECT_SET(json, pid, %d, recv_holder_taskinfo->pid);
688 JSON_OBJECT_SET(json, process, "%s", recv_holder_taskinfo->processName);
689
690 printf(" -> %6d %8d 0x%016llx 0x%08x (%d) %s\n",
691 port_status.mps_qlimit,
692 port_status.mps_msgcount,
693 (uint64_t)port_context,
694 recv_name,
695 recv_holder_taskinfo->pid,
696 recv_holder_taskinfo->processName);
697
698 } else {
699 JSON_OBJECT_SET(json, identifier, "0x%08x", 0);
700 JSON_OBJECT_SET(json, pid, %d, -1);
701 JSON_OBJECT_SET(json, process, "unknown");
702 printf(" 0x00000000 (-) Unknown Process\n");
703 }
704
705 JSON_OBJECT_END(json); // non-kobject
706 }
707
708 uint32_t print_hex_data(char *outstr, uint32_t maxlen, char *prefix, char *desc, void *addr, int len) {
709 int i;
710 unsigned char buff[17];
711 unsigned char *pc = addr;
712 uint32_t plen = 0;
713
714 if (desc != NULL)
715 plen += snprintf(&outstr[plen], safesize(maxlen - plen), "%s%s:\n", prefix, desc);
716
717 for (i = 0; i < len; i++) {
718
719 if ((i % 16) == 0) {
720 if (i != 0)
721 plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %s\n", buff);
722
723 plen += snprintf(&outstr[plen], safesize(maxlen - plen), "%s %04x ", prefix, i);
724 }
725
726 plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %02x", pc[i]);
727
728 if ((pc[i] < 0x20) || (pc[i] > 0x7e))
729 buff[i % 16] = '.';
730 else
731 buff[i % 16] = pc[i];
732 buff[(i % 16) + 1] = '\0';
733 }
734
735 while ((i % 16) != 0) {
736 plen += snprintf(&outstr[plen], safesize(maxlen - plen), " ");
737 i++;
738 }
739
740 plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %s\n", buff);
741
742 return plen;
743 }