2 * Copyright (c) 2002-2016 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
28 #include <mach/mach.h>
29 //#include <mach/mach_port.h.h>
30 #include <mach/mach_voucher.h>
34 const char * kobject_name(natural_t kotype
)
37 case IKOT_NONE
: return "message-queue";
38 case IKOT_THREAD_CONTROL
: return "THREAD-CONTROL";
39 case IKOT_TASK_CONTROL
: return "TASK-CONTROL";
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_EVENTLINK
: return "EVENTLINK";
81 case IKOT_TASK_INSPECT
: return "TASK-INSPECT";
82 case IKOT_TASK_READ
: return "TASK-READ";
83 case IKOT_THREAD_INSPECT
: return "THREAD-INSPECT";
84 case IKOT_THREAD_READ
: return "THREAD-READ";
85 case IKOT_SUID_CRED
: return "SUID_CRED";
86 case IKOT_HYPERVISOR
: return "HYPERVISOR";
88 default: return "UNKNOWN";
92 const port_status_flag_info_t port_status_flags
[] = {
93 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TEMPOWNER
)] = {
94 .flag
= MACH_PORT_STATUS_FLAG_TEMPOWNER
,
98 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_GUARDED
)] = {
99 .flag
= MACH_PORT_STATUS_FLAG_GUARDED
,
103 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_STRICT_GUARD
)] = {
104 .flag
= MACH_PORT_STATUS_FLAG_STRICT_GUARD
,
106 .name
= "strict guard",
108 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_IMP_DONATION
)] = {
109 .flag
= MACH_PORT_STATUS_FLAG_IMP_DONATION
,
111 .name
= "imp donation",
113 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_REVIVE
)] = {
114 .flag
= MACH_PORT_STATUS_FLAG_REVIVE
,
118 [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TASKPTR
)] = {
119 .flag
= MACH_PORT_STATUS_FLAG_TASKPTR
,
126 #define VOUCHER_DETAIL_PREFIX " "
128 static const unsigned int voucher_contents_size
= 8192;
129 static uint8_t voucher_contents
[voucher_contents_size
];
140 } task_table_entry_counts
;
142 typedef task_table_entry_counts
* task_table_entry_counts_t
;
144 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
);
146 static uint32_t safesize (int len
){
147 return (len
> 0) ? len
: 0;
150 uint32_t show_recipe_detail(mach_voucher_attr_recipe_t recipe
, char *voucher_outstr
, uint32_t maxlen
, JSON_t json
) {
151 JSON_OBJECT_BEGIN(json
);
154 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), VOUCHER_DETAIL_PREFIX
"Key: %u, ", recipe
->key
);
155 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), "Command: %u, ", recipe
->command
);
156 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), "Previous voucher: 0x%x, ", recipe
->previous_voucher
);
157 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), "Content size: %u\n", recipe
->content_size
);
159 JSON_OBJECT_SET(json
, key
, %u
, recipe
->key
);
160 JSON_OBJECT_SET(json
, command
, %u
, recipe
->command
);
161 JSON_OBJECT_SET(json
, previous_voucher
, "0x%x", recipe
->previous_voucher
);
162 JSON_OBJECT_SET(json
, content_size
, %u
, recipe
->content_size
);
164 switch (recipe
->key
) {
165 case MACH_VOUCHER_ATTR_KEY_IMPORTANCE
:
166 // content may not be valid JSON, exclude
167 // JSON_OBJECT_SET(json, importance_info, "%s", (char *)recipe->content);
168 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), VOUCHER_DETAIL_PREFIX
"IMPORTANCE INFO: %s", (char *)recipe
->content
);
170 case MACH_VOUCHER_ATTR_KEY_BANK
:
171 // content may not be valid JSON, exclude
172 // JSON_OBJECT_SET(json, resource_accounting_info, "%s", (char *)recipe->content);
173 len
+= snprintf(&voucher_outstr
[len
], safesize(maxlen
- len
), VOUCHER_DETAIL_PREFIX
"RESOURCE ACCOUNTING INFO: %s", (char *)recipe
->content
);
176 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
));
180 if (len
+ 1 < maxlen
&& voucher_outstr
[len
- 1] != '\n') {
181 voucher_outstr
[len
++] = '\n';
182 voucher_outstr
[len
] = '\0';
184 JSON_OBJECT_END(json
); // recipe
189 char * copy_voucher_detail(mach_port_t task
, mach_port_name_t voucher
, JSON_t json
) {
190 unsigned int recipe_size
= voucher_contents_size
;
191 kern_return_t kr
= KERN_SUCCESS
;
192 bzero((void *)&voucher_contents
[0], sizeof(voucher_contents
));
193 unsigned v_kobject
= 0;
194 unsigned v_kotype
= 0;
195 uint32_t detail_maxlen
= VOUCHER_DETAIL_MAXLEN
;
196 char * voucher_outstr
= (char *)malloc(detail_maxlen
);
197 voucher_outstr
[0] = '\0';
200 kr
= mach_port_kernel_object( task
,
202 &v_kotype
, (unsigned *)&v_kobject
);
203 if (kr
== KERN_SUCCESS
&& v_kotype
== IKOT_VOUCHER
) {
205 kr
= mach_voucher_debug_info(task
, voucher
,
206 (mach_voucher_attr_raw_recipe_array_t
)&voucher_contents
[0],
208 if (kr
!= KERN_SUCCESS
&& kr
!= KERN_NOT_SUPPORTED
) {
209 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
));
210 return voucher_outstr
;
213 if (recipe_size
== 0) {
214 plen
+= snprintf(&voucher_outstr
[plen
], safesize(detail_maxlen
- plen
), VOUCHER_DETAIL_PREFIX
"Voucher: 0x%x has no contents\n", v_kobject
);
215 return voucher_outstr
;
218 plen
+= snprintf(&voucher_outstr
[plen
], safesize(detail_maxlen
- plen
), VOUCHER_DETAIL_PREFIX
"Voucher: 0x%x\n", v_kobject
);
219 unsigned int used_size
= 0;
220 mach_voucher_attr_recipe_t recipe
= NULL
;
221 while (recipe_size
> used_size
) {
222 recipe
= (mach_voucher_attr_recipe_t
)&voucher_contents
[used_size
];
224 plen
+= show_recipe_detail(recipe
, &voucher_outstr
[plen
], safesize(detail_maxlen
- plen
), json
);
226 used_size
+= sizeof(mach_voucher_attr_recipe_data_t
) + recipe
->content_size
;
229 plen
+= snprintf(&voucher_outstr
[plen
], safesize(detail_maxlen
- plen
), VOUCHER_DETAIL_PREFIX
"Invalid voucher: 0x%x\n", voucher
);
232 return voucher_outstr
;
235 void get_receive_port_context(task_read_t taskp
, mach_port_name_t portname
, mach_port_context_t
*context
) {
236 if (context
== NULL
) {
241 ret
= mach_port_get_context(taskp
, portname
, context
);
242 if (ret
!= KERN_SUCCESS
) {
243 fprintf(stderr
, "mach_port_get_context(0x%08x) failed: %s\n",
245 mach_error_string(ret
));
246 *context
= (mach_port_context_t
)0;
251 int get_recieve_port_status(task_read_t taskp
, mach_port_name_t portname
, mach_port_info_ext_t
*info
){
255 mach_msg_type_number_t statusCnt
;
257 statusCnt
= MACH_PORT_INFO_EXT_COUNT
;
258 ret
= mach_port_get_attributes(taskp
,
261 (mach_port_info_t
)info
,
263 if (ret
!= KERN_SUCCESS
) {
264 fprintf(stderr
, "mach_port_get_attributes(0x%08x) failed: %s\n",
266 mach_error_string(ret
));
273 void show_task_mach_ports(my_per_task_info_t
*taskinfo
, uint32_t taskCount
, my_per_task_info_t
*allTaskInfos
, JSON_t json
)
276 task_table_entry_counts counts
= {0};
278 counts
.total
= taskinfo
->tableCount
+ taskinfo
->treeCount
;
280 JSON_KEY(json
, ports
)
281 JSON_ARRAY_BEGIN(json
);
283 printf(" name ipc-object rights flags boost reqs recv send sonce oref qlimit msgcount context identifier type\n");
284 printf("--------- ---------- ---------- -------- ----- ---- ----- ----- ----- ---- ------ -------- ------------------ ----------- ------------\n");
285 for (i
= 0; i
< taskinfo
->tableCount
; i
++) {
286 show_task_table_entry(&taskinfo
->table
[i
], taskinfo
, taskCount
, allTaskInfos
, &counts
, json
);
289 JSON_ARRAY_END(json
); // ports
290 JSON_OBJECT_SET(json
, total
, %d
, counts
.total
);
291 JSON_OBJECT_SET(json
, send_rights
, %d
, counts
.sendcount
);
292 JSON_OBJECT_SET(json
, receive_rights
, %d
, counts
.receivecount
);
293 JSON_OBJECT_SET(json
, send_once_rights
, %d
, counts
.sendoncecount
);
294 JSON_OBJECT_SET(json
, port_sets
, %d
, counts
.portsetcount
);
295 JSON_OBJECT_SET(json
, dead_names
, %d
, counts
.deadcount
);
296 JSON_OBJECT_SET(json
, dead_name requests
, %d
, counts
.dncount
);
297 JSON_OBJECT_SET(json
, vouchers
, %d
, counts
.vouchercount
);
300 printf("total = %d\n", counts
.total
);
301 printf("SEND = %d\n", counts
.sendcount
);
302 printf("RECEIVE = %d\n", counts
.receivecount
);
303 printf("SEND_ONCE = %d\n", counts
.sendoncecount
);
304 printf("PORT_SET = %d\n", counts
.portsetcount
);
305 printf("DEAD_NAME = %d\n", counts
.deadcount
);
306 printf("DNREQUEST = %d\n", counts
.dncount
);
307 printf("VOUCHERS = %d\n", counts
.vouchercount
);
310 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
) {
311 int j
, k
, port_status_flag_idx
;
313 boolean_t send
= FALSE
;
314 boolean_t dnreq
= FALSE
;
316 unsigned int kotype
= 0;
317 vm_offset_t kobject
= (vm_offset_t
)0;
318 kobject_description_t desc
;
319 mach_vm_address_t kaddr
;
321 /* skip empty slots in the table */
322 if ((entry
->iin_type
& MACH_PORT_TYPE_ALL_RIGHTS
) == 0) {
327 if (entry
->iin_type
== MACH_PORT_TYPE_PORT_SET
) {
328 mach_port_name_array_t members
;
329 mach_msg_type_number_t membersCnt
;
331 ret
= mach_port_get_set_status(taskinfo
->task
,
333 &members
, &membersCnt
);
334 if (ret
!= KERN_SUCCESS
) {
335 fprintf(stderr
, "mach_port_get_set_status(0x%08x) failed: %s\n",
337 mach_error_string(ret
));
341 JSON_OBJECT_BEGIN(json
);
342 JSON_OBJECT_SET(json
, type
, "port set");
343 JSON_OBJECT_SET(json
, name
, "0x%08x", entry
->iin_name
);
344 JSON_OBJECT_SET(json
, ipc
-object
, "0x%08x", entry
->iin_object
);
346 JSON_KEY(json
, members
);
347 JSON_ARRAY_BEGIN(json
);
349 printf("0x%08x 0x%08x port-set -------- --- 1 %d members\n",
353 /* get some info for each portset member */
354 for (j
= 0; j
< membersCnt
; j
++) {
355 for (k
= 0; k
< taskinfo
->tableCount
; k
++) {
356 if (taskinfo
->table
[k
].iin_name
== members
[j
]) {
357 mach_port_info_ext_t info
;
358 mach_port_status_t port_status
;
359 mach_port_context_t port_context
= (mach_port_context_t
)0;
360 if (0 != get_recieve_port_status(taskinfo
->task
, taskinfo
->table
[k
].iin_name
, &info
)) {
361 bzero((void *)&info
, sizeof(info
));
363 port_status
= info
.mpie_status
;
364 get_receive_port_context(taskinfo
->task
, taskinfo
->table
[k
].iin_name
, &port_context
);
366 JSON_OBJECT_BEGIN(json
);
367 JSON_OBJECT_SET(json
, ipc
-object
, "0x%08x", taskinfo
->table
[k
].iin_object
);
369 JSON_KEY(json
, rights
);
370 JSON_ARRAY_BEGIN(json
);
371 JSON_ARRAY_APPEND(json
, "recv");
372 if (taskinfo
->table
[k
].iin_type
& MACH_PORT_TYPE_SEND
) {
373 JSON_ARRAY_APPEND(json
, "send");
375 JSON_ARRAY_END(json
); // rights
377 JSON_KEY(json
, port_status_flags
);
378 JSON_ARRAY_BEGIN(json
);
379 port_status_flag_idx
= 0;
380 while (0 != port_status_flags
[port_status_flag_idx
++].flag
) {
381 if (port_status
.mps_flags
& INDEX_TO_PORT_FLAG(port_status_flag_idx
)) {
382 JSON_ARRAY_APPEND(json
, "%s", port_status_flags
[port_status_flag_idx
].name
);
385 JSON_ARRAY_END(json
); // port status flags
386 JSON_OBJECT_SET(json
, boosts
, %d
, info
.mpie_boost_cnt
);
388 JSON_KEY(json
, notifications
);
389 JSON_ARRAY_BEGIN(json
);
390 if (taskinfo
->table
[k
].iin_type
& MACH_PORT_TYPE_DNREQUEST
) {
391 JSON_ARRAY_APPEND(json
, "dead name");
393 if (port_status
.mps_nsrequest
) {
394 JSON_ARRAY_APPEND(json
, "no sender");
396 if (port_status
.mps_nsrequest
) {
397 JSON_ARRAY_APPEND(json
, "port destroy request");
399 JSON_ARRAY_END(json
); // notifications
401 JSON_OBJECT_SET(json
, recv_rights
, %d
, 1);
402 JSON_OBJECT_SET(json
, send_rights
, %d
, taskinfo
->table
[k
].iin_urefs
);
403 JSON_OBJECT_SET(json
, send_once_rights
, %d
, port_status
.mps_sorights
);
404 JSON_OBJECT_SET_BOOL(json
, oref
, port_status
.mps_srights
);
405 JSON_OBJECT_SET(json
, queue_limit
, %d
, port_status
.mps_qlimit
);
406 JSON_OBJECT_SET(json
, msg_count
, %d
, port_status
.mps_msgcount
);
407 JSON_OBJECT_SET(json
, context
, "0x%016llx", (uint64_t)port_context
);
408 JSON_OBJECT_SET(json
, identifier
, "0x%08x", taskinfo
->table
[k
].iin_name
);
409 JSON_OBJECT_SET(json
, pid
, %d
, taskinfo
->pid
);
410 JSON_OBJECT_SET(json
, process
, "%s", taskinfo
->processName
);
411 JSON_OBJECT_END(json
); // member
413 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",
414 taskinfo
->table
[k
].iin_object
,
415 (taskinfo
->table
[k
].iin_type
& MACH_PORT_TYPE_SEND
) ? "recv,send ":"recv ",
416 SHOW_PORT_STATUS_FLAGS(port_status
.mps_flags
),
418 (taskinfo
->table
[k
].iin_type
& MACH_PORT_TYPE_DNREQUEST
) ? "D" : "-",
419 (port_status
.mps_nsrequest
) ? "N" : "-",
420 (port_status
.mps_pdrequest
) ? "P" : "-",
422 taskinfo
->table
[k
].iin_urefs
,
423 port_status
.mps_sorights
,
424 (port_status
.mps_srights
) ? "Y" : "N",
425 port_status
.mps_qlimit
,
426 port_status
.mps_msgcount
,
427 (uint64_t)port_context
,
428 taskinfo
->table
[k
].iin_name
,
430 taskinfo
->processName
);
436 JSON_ARRAY_END(json
); // members
437 JSON_OBJECT_END(json
); // port-set
439 ret
= vm_deallocate(mach_task_self(), (vm_address_t
)members
,
440 membersCnt
* sizeof(mach_port_name_t
));
441 if (ret
!= KERN_SUCCESS
) {
442 fprintf(stderr
, "vm_deallocate() failed: %s\n",
443 mach_error_string(ret
));
446 counts
->portsetcount
++;
450 if (entry
->iin_type
& MACH_PORT_TYPE_SEND
) {
452 sendrights
= entry
->iin_urefs
;
456 if (entry
->iin_type
& MACH_PORT_TYPE_DNREQUEST
) {
461 if (entry
->iin_type
& MACH_PORT_TYPE_RECEIVE
) {
462 mach_port_status_t status
;
463 mach_port_info_ext_t info
;
464 mach_port_context_t context
= (mach_port_context_t
)0;
465 struct k2n_table_node
*k2nnode
;
466 ret
= get_recieve_port_status(taskinfo
->task
, entry
->iin_name
, &info
);
467 get_receive_port_context(taskinfo
->task
, entry
->iin_name
, &context
);
468 /* its ok to fail in fetching attributes */
472 status
= info
.mpie_status
;
474 JSON_OBJECT_BEGIN(json
);
475 JSON_OBJECT_SET(json
, type
, "port");
476 JSON_OBJECT_SET(json
, name
, "0x%08x", entry
->iin_name
);
477 JSON_OBJECT_SET(json
, ipc
-object
, "0x%08x", entry
->iin_object
);
479 JSON_KEY(json
, rights
);
480 JSON_ARRAY_BEGIN(json
);
481 JSON_ARRAY_APPEND(json
, "recv");
482 if (send
) JSON_ARRAY_APPEND(json
, "send");
483 JSON_ARRAY_END(json
); // rights
485 JSON_KEY(json
, port_status_flags
);
486 JSON_ARRAY_BEGIN(json
);
487 port_status_flag_idx
= 0;
488 while (0 != port_status_flags
[port_status_flag_idx
++].flag
) {
489 if (status
.mps_flags
& INDEX_TO_PORT_FLAG(port_status_flag_idx
)) {
490 JSON_ARRAY_APPEND(json
, "%s", port_status_flags
[port_status_flag_idx
].name
);
493 JSON_ARRAY_END(json
); // port status flags
494 JSON_OBJECT_SET(json
, boosts
, %d
, info
.mpie_boost_cnt
);
496 JSON_KEY(json
, notifications
);
497 JSON_ARRAY_BEGIN(json
);
499 JSON_ARRAY_APPEND(json
, "dead name");
501 if (status
.mps_nsrequest
) {
502 JSON_ARRAY_APPEND(json
, "no sender");
504 if (status
.mps_nsrequest
) {
505 JSON_ARRAY_APPEND(json
, "port destroy request");
507 JSON_ARRAY_END(json
); // notifications
509 JSON_OBJECT_SET(json
, recv_rights
, %d
, 1);
510 JSON_OBJECT_SET(json
, send_rights
, %d
, sendrights
);
511 JSON_OBJECT_SET(json
, send_once_rights
, %d
, status
.mps_sorights
);
512 JSON_OBJECT_SET_BOOL(json
, oref
, status
.mps_srights
);
513 JSON_OBJECT_SET(json
, queue_limit
, %d
, status
.mps_qlimit
);
514 JSON_OBJECT_SET(json
, msg_count
, %d
, status
.mps_msgcount
);
515 JSON_OBJECT_SET(json
, context
, "0x%016llx", (uint64_t)context
);
516 JSON_OBJECT_END(json
); // port
518 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",
521 (send
) ? "recv,send ":"recv ",
522 SHOW_PORT_STATUS_FLAGS(status
.mps_flags
),
525 (status
.mps_nsrequest
) ? "N":"-",
526 (status
.mps_pdrequest
) ? "P":"-",
530 (status
.mps_srights
) ? "Y":"N",
534 counts
->receivecount
++;
536 /* show other rights (in this and other tasks) for the port */
537 for (j
= 0; j
< taskCount
; j
++) {
538 if (allTaskInfos
[j
].valid
== FALSE
)
541 k2nnode
= k2n_table_lookup(allTaskInfos
[j
].k2ntable
, entry
->iin_object
);
544 if (k2nnode
->info_name
!= entry
) {
545 assert(k2nnode
->info_name
->iin_object
== entry
->iin_object
);
547 printf(" + %s -------- %s%s%s %5d <- 0x%08x (%d) %s\n",
548 (k2nnode
->info_name
->iin_type
& MACH_PORT_TYPE_SEND_ONCE
) ?
549 "send-once " : "send ",
550 (k2nnode
->info_name
->iin_type
& MACH_PORT_TYPE_DNREQUEST
) ? "D" : "-",
553 k2nnode
->info_name
->iin_urefs
,
554 k2nnode
->info_name
->iin_name
,
556 allTaskInfos
[j
].processName
);
559 k2nnode
= k2n_table_lookup_next(k2nnode
, entry
->iin_object
);
564 else if (entry
->iin_type
& MACH_PORT_TYPE_DEAD_NAME
)
566 JSON_OBJECT_BEGIN(json
);
567 JSON_OBJECT_SET(json
, type
, "dead name");
568 JSON_OBJECT_SET(json
, name
, "0x%08x", entry
->iin_name
);
569 JSON_OBJECT_SET(json
, ipc
-object
, "0x%08x", entry
->iin_object
);
570 JSON_OBJECT_SET(json
, send_rights
, %d
, entry
->iin_urefs
);
571 JSON_OBJECT_END(json
); // dead name
573 printf("0x%08x 0x%08x dead-name -------- --- %5d \n",
581 if (entry
->iin_type
& MACH_PORT_TYPE_SEND_ONCE
) {
582 counts
->sendoncecount
++;
585 JSON_OBJECT_BEGIN(json
);
586 JSON_OBJECT_SET(json
, name
, "0x%08x", entry
->iin_name
);
587 JSON_OBJECT_SET(json
, ipc
-object
, "0x%08x", entry
->iin_object
);
589 JSON_KEY(json
, rights
);
590 JSON_ARRAY_BEGIN(json
);
591 JSON_ARRAY_APPEND(json
, "%s", (send
) ? "send":"send once");
592 JSON_ARRAY_END(json
); //rights
594 JSON_KEY(json
, notifications
);
595 JSON_ARRAY_BEGIN(json
);
596 if (dnreq
) JSON_ARRAY_APPEND(json
, "dead name");
597 JSON_ARRAY_END(json
); // notifications
599 JSON_OBJECT_SET(json
, send_rights
, %d
, (send
) ? sendrights
: 0);
601 printf("0x%08x 0x%08x %s -------- %s%s%s %5.0d ",
604 (send
) ? "send ":"send-once ",
608 (send
) ? sendrights
: 0);
610 /* converting to kobjects is not always supported */
613 ret
= mach_port_kobject_description(taskinfo
->task
,
617 if (KERN_SUCCESS
== ret
) {
618 kobject
= (unsigned) kaddr
;
620 ret
= mach_port_kernel_object(taskinfo
->task
,
622 &kotype
, (unsigned *)&kobject
);
625 if (ret
== KERN_SUCCESS
&& kotype
!= 0) {
626 JSON_OBJECT_SET(json
, identifier
, "0x%08x", (natural_t
)kobject
);
627 JSON_OBJECT_SET(json
, type
, "%s", kobject_name(kotype
));
630 JSON_OBJECT_SET(json
, description
, "%s", desc
);
631 printf(" 0x%08x %s %s", (natural_t
)kobject
, kobject_name(kotype
), desc
);
633 printf(" 0x%08x %s", (natural_t
)kobject
, kobject_name(kotype
));
636 if ((kotype
== IKOT_TASK_RESUME
) ||
637 (kotype
== IKOT_TASK_CONTROL
) ||
638 (kotype
== IKOT_TASK_READ
) ||
639 (kotype
== IKOT_TASK_INSPECT
) ||
640 (kotype
== IKOT_TASK_NAME
)) {
641 if (taskinfo
->task_kobject
== kobject
) {
642 /* neat little optimization since in most cases tasks have themselves in their ipc space */
643 JSON_OBJECT_SET(json
, pid
, %d
, taskinfo
->pid
);
644 JSON_OBJECT_SET(json
, process
, "%s", taskinfo
->processName
);
645 printf(" SELF (%d) %s", taskinfo
->pid
, taskinfo
->processName
);
647 my_per_task_info_t
* _found_task
= get_taskinfo_by_kobject((natural_t
)kobject
);
648 JSON_OBJECT_SET(json
, pid
, %d
, _found_task
->pid
);
649 JSON_OBJECT_SET(json
, process
, "%s", _found_task
->processName
);
650 printf(" (%d) %s", _found_task
->pid
, _found_task
->processName
);
654 if ((kotype
== IKOT_THREAD_CONTROL
) ||
655 (kotype
== IKOT_THREAD_READ
) ||
656 (kotype
== IKOT_THREAD_INSPECT
)) {
657 for (int i
= 0; i
< taskinfo
->threadCount
; i
++) {
658 if (taskinfo
->threadInfos
[i
].th_kobject
== kobject
) {
659 printf(" (%#llx)", taskinfo
->threadInfos
[i
].th_id
);
666 if (kotype
== IKOT_VOUCHER
) {
667 counts
->vouchercount
++;
668 if (lsmp_config
.show_voucher_details
) {
669 JSON_KEY(json
, recipes
);
670 JSON_ARRAY_BEGIN(json
);
671 char * detail
= copy_voucher_detail(taskinfo
->task
, entry
->iin_name
, json
);
672 JSON_ARRAY_END(json
); // recipes
673 printf("%s\n", detail
);
677 JSON_OBJECT_END(json
); // kobject
681 /* not kobject - find the receive right holder */
682 my_per_task_info_t
*recv_holder_taskinfo
;
683 mach_port_name_t recv_name
= MACH_PORT_NULL
;
684 if (KERN_SUCCESS
== get_taskinfo_of_receiver_by_send_right(*entry
, &recv_holder_taskinfo
, &recv_name
)) {
685 mach_port_status_t port_status
;
686 mach_port_info_ext_t info
;
687 mach_port_context_t port_context
= (mach_port_context_t
)0;
688 if (0 != get_recieve_port_status(recv_holder_taskinfo
->task
, recv_name
, &info
)) {
689 bzero((void *)&port_status
, sizeof(port_status
));
691 port_status
= info
.mpie_status
;
692 get_receive_port_context(recv_holder_taskinfo
->task
, recv_name
, &port_context
);
694 JSON_OBJECT_SET(json
, queue_limit
, %d
, port_status
.mps_qlimit
);
695 JSON_OBJECT_SET(json
, msg_count
, %d
, port_status
.mps_msgcount
);
696 JSON_OBJECT_SET(json
, context
, "0x%016llx", (uint64_t)port_context
);
697 JSON_OBJECT_SET(json
, identifier
, "0x%08x", recv_name
);
698 JSON_OBJECT_SET(json
, pid
, %d
, recv_holder_taskinfo
->pid
);
699 JSON_OBJECT_SET(json
, process
, "%s", recv_holder_taskinfo
->processName
);
701 printf(" -> %6d %8d 0x%016llx 0x%08x (%d) %s\n",
702 port_status
.mps_qlimit
,
703 port_status
.mps_msgcount
,
704 (uint64_t)port_context
,
706 recv_holder_taskinfo
->pid
,
707 recv_holder_taskinfo
->processName
);
710 JSON_OBJECT_SET(json
, identifier
, "0x%08x", 0);
711 JSON_OBJECT_SET(json
, pid
, %d
, -1);
712 JSON_OBJECT_SET(json
, process
, "unknown");
713 printf(" 0x00000000 (-) Unknown Process\n");
716 JSON_OBJECT_END(json
); // non-kobject
719 uint32_t print_hex_data(char *outstr
, uint32_t maxlen
, char *prefix
, char *desc
, void *addr
, int len
) {
721 unsigned char buff
[17];
722 unsigned char *pc
= addr
;
726 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), "%s%s:\n", prefix
, desc
);
728 for (i
= 0; i
< len
; i
++) {
732 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), " %s\n", buff
);
734 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), "%s %04x ", prefix
, i
);
737 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), " %02x", pc
[i
]);
739 if ((pc
[i
] < 0x20) || (pc
[i
] > 0x7e))
742 buff
[i
% 16] = pc
[i
];
743 buff
[(i
% 16) + 1] = '\0';
746 while ((i
% 16) != 0) {
747 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), " ");
751 plen
+= snprintf(&outstr
[plen
], safesize(maxlen
- plen
), " %s\n", buff
);