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