X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/ac27e6b4e9f2f269ad11856171ae8e1f51fa26f0..530d02b6d6489eaa76ff9853c2897b2dc48d2d8e:/lsmp.tproj/port_details.c diff --git a/lsmp.tproj/port_details.c b/lsmp.tproj/port_details.c index 985fb89..619bf02 100644 --- a/lsmp.tproj/port_details.c +++ b/lsmp.tproj/port_details.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-20014 Apple Inc. All rights reserved. + * Copyright (c) 2002-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -24,9 +24,11 @@ #include #include #include +#include #include #include #include "common.h" +#include "json.h" const char * kobject_name(natural_t kotype) { @@ -75,41 +77,108 @@ const char * kobject_name(natural_t kotype) } } +const port_status_flag_info_t port_status_flags[] = { + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TEMPOWNER)] = { + .flag = MACH_PORT_STATUS_FLAG_TEMPOWNER, + .compact_name = "T", + .name = "tempowner", + }, + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_GUARDED)] = { + .flag = MACH_PORT_STATUS_FLAG_GUARDED, + .compact_name = "G", + .name = "guarded", + }, + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_STRICT_GUARD)] = { + .flag = MACH_PORT_STATUS_FLAG_STRICT_GUARD, + .compact_name = "S", + .name = "strict guard", + }, + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_IMP_DONATION)] = { + .flag = MACH_PORT_STATUS_FLAG_IMP_DONATION, + .compact_name = "I", + .name = "imp donation", + }, + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_REVIVE)] = { + .flag = MACH_PORT_STATUS_FLAG_REVIVE, + .compact_name = "R", + .name = "revive", + }, + [PORT_FLAG_TO_INDEX(MACH_PORT_STATUS_FLAG_TASKPTR)] = { + .flag = MACH_PORT_STATUS_FLAG_TASKPTR, + .compact_name = "P", + .name = "taskptr", + }, + {0}, +}; + #define VOUCHER_DETAIL_PREFIX " " static const unsigned int voucher_contents_size = 8192; static uint8_t voucher_contents[voucher_contents_size]; +typedef struct { + int total; + int sendcount; + int receivecount; + int sendoncecount; + int portsetcount; + int deadcount; + int dncount; + int vouchercount; +} task_table_entry_counts; + +typedef task_table_entry_counts * task_table_entry_counts_t; + +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); static uint32_t safesize (int len){ - return (len > 0)? len : 0; + return (len > 0) ? len : 0; } -void show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, uint32_t maxlen) { +uint32_t show_recipe_detail(mach_voucher_attr_recipe_t recipe, char *voucher_outstr, uint32_t maxlen, JSON_t json) { + JSON_OBJECT_BEGIN(json); + uint32_t len = 0; - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "Key: %u, ", recipe->key)); - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Command: %u, ", recipe->command)); - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Previous voucher: 0x%x, ", recipe->previous_voucher)); - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, "Content size: %u\n", recipe->content_size)); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "Key: %u, ", recipe->key); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Command: %u, ", recipe->command); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Previous voucher: 0x%x, ", recipe->previous_voucher); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), "Content size: %u\n", recipe->content_size); + + JSON_OBJECT_SET(json, key, %u, recipe->key); + JSON_OBJECT_SET(json, command, %u, recipe->command); + JSON_OBJECT_SET(json, previous_voucher, "0x%x", recipe->previous_voucher); + JSON_OBJECT_SET(json, content_size, %u, recipe->content_size); + switch (recipe->key) { case MACH_VOUCHER_ATTR_KEY_ATM: - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "ATM ID: %llu\n", *(uint64_t *)(uintptr_t)recipe->content)); + JSON_OBJECT_SET(json, ATM_ID, %llu, *(uint64_t *)(uintptr_t)recipe->content); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "ATM ID: %llu", *(uint64_t *)(uintptr_t)recipe->content); break; case MACH_VOUCHER_ATTR_KEY_IMPORTANCE: - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "IMPORTANCE INFO: %s\n", (char *)recipe->content)); + // content may not be valid JSON, exclude + // JSON_OBJECT_SET(json, importance_info, "%s", (char *)recipe->content); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "IMPORTANCE INFO: %s", (char *)recipe->content); break; case MACH_VOUCHER_ATTR_KEY_BANK: - len += safesize(snprintf(&voucher_outstr[len], maxlen - len, VOUCHER_DETAIL_PREFIX "RESOURCE ACCOUNTING INFO: %s\n", (char *)recipe->content)); + // content may not be valid JSON, exclude + // JSON_OBJECT_SET(json, resource_accounting_info, "%s", (char *)recipe->content); + len += snprintf(&voucher_outstr[len], safesize(maxlen - len), VOUCHER_DETAIL_PREFIX "RESOURCE ACCOUNTING INFO: %s", (char *)recipe->content); break; default: - 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)); + 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)); break; } + if (len + 1 < maxlen && voucher_outstr[len - 1] != '\n') { + voucher_outstr[len++] = '\n'; + voucher_outstr[len] = '\0'; + } + JSON_OBJECT_END(json); // recipe + return len; } -char * copy_voucher_detail(mach_port_t task, mach_port_name_t voucher) { +char * copy_voucher_detail(mach_port_t task, mach_port_name_t voucher, JSON_t json) { unsigned int recipe_size = voucher_contents_size; kern_return_t kr = KERN_SUCCESS; bzero((void *)&voucher_contents[0], sizeof(voucher_contents)); @@ -129,29 +198,29 @@ char * copy_voucher_detail(mach_port_t task, mach_port_name_t voucher) { (mach_voucher_attr_raw_recipe_array_t)&voucher_contents[0], &recipe_size); if (kr != KERN_SUCCESS && kr != KERN_NOT_SUPPORTED) { - 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))); + 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)); return voucher_outstr; } if (recipe_size == 0) { - plen += safesize(snprintf(&voucher_outstr[plen], detail_maxlen - plen, VOUCHER_DETAIL_PREFIX "Voucher: 0x%x has no contents\n", v_kobject)); + plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Voucher: 0x%x has no contents\n", v_kobject); return voucher_outstr; } - plen += safesize(snprintf(&voucher_outstr[plen], detail_maxlen - plen, VOUCHER_DETAIL_PREFIX "Voucher: 0x%x\n", v_kobject)); + plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Voucher: 0x%x\n", v_kobject); unsigned int used_size = 0; mach_voucher_attr_recipe_t recipe = NULL; while (recipe_size > used_size) { recipe = (mach_voucher_attr_recipe_t)&voucher_contents[used_size]; if (recipe->key) { - show_recipe_detail(recipe, &voucher_outstr[plen], detail_maxlen - plen); + plen += show_recipe_detail(recipe, &voucher_outstr[plen], safesize(detail_maxlen - plen), json); } used_size += sizeof(mach_voucher_attr_recipe_data_t) + recipe->content_size; } } else { - plen += safesize(snprintf(&voucher_outstr[plen], detail_maxlen - plen, VOUCHER_DETAIL_PREFIX "Invalid voucher: 0x%x\n", voucher)); + plen += snprintf(&voucher_outstr[plen], safesize(detail_maxlen - plen), VOUCHER_DETAIL_PREFIX "Invalid voucher: 0x%x\n", voucher); } - + return voucher_outstr; } @@ -159,7 +228,7 @@ void get_receive_port_context(task_t taskp, mach_port_name_t portname, mach_port if (context == NULL) { return; } - + kern_return_t ret; ret = mach_port_get_context(taskp, portname, context); if (ret != KERN_SUCCESS) { @@ -189,278 +258,463 @@ int get_recieve_port_status(task_t taskp, mach_port_name_t portname, mach_port_i mach_error_string(ret)); return -1; } - + return 0; } -void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos) +void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos, JSON_t json) { - int i, emptycount = 0, portsetcount = 0, sendcount = 0, receivecount = 0, sendoncecount = 0, deadcount = 0, dncount = 0, vouchercount = 0, pid; - kern_return_t ret; - pid_for_task(taskinfo->task, &pid); - + int i; + task_table_entry_counts counts = {0}; + + counts.total = taskinfo->tableCount + taskinfo->treeCount; + + JSON_KEY(json, ports) + JSON_ARRAY_BEGIN(json); + printf(" name ipc-object rights flags boost reqs recv send sonce oref qlimit msgcount context identifier type\n"); printf("--------- ---------- ---------- -------- ----- ---- ----- ----- ----- ---- ------ -------- ------------------ ----------- ------------\n"); - for (i = 0; i < taskinfo->tableCount; i++) { - int j, k; - boolean_t send = FALSE; - boolean_t sendonce = FALSE; - boolean_t dnreq = FALSE; - int sendrights = 0; - unsigned int kotype = 0; - vm_offset_t kobject = (vm_offset_t)0; - - /* skip empty slots in the table */ - if ((taskinfo->table[i].iin_type & MACH_PORT_TYPE_ALL_RIGHTS) == 0) { - emptycount++; - continue; + for (i = 0; i < taskinfo->tableCount; i++) { + show_task_table_entry(&taskinfo->table[i], taskinfo, taskCount, allTaskInfos, &counts, json); + } + + JSON_ARRAY_END(json); // ports + JSON_OBJECT_SET(json, total, %d, counts.total); + JSON_OBJECT_SET(json, send_rights, %d, counts.sendcount); + JSON_OBJECT_SET(json, receive_rights, %d, counts.receivecount); + JSON_OBJECT_SET(json, send_once_rights, %d, counts.sendoncecount); + JSON_OBJECT_SET(json, port_sets, %d, counts.portsetcount); + JSON_OBJECT_SET(json, dead_names, %d, counts.deadcount); + JSON_OBJECT_SET(json, dead_name requests, %d, counts.dncount); + JSON_OBJECT_SET(json, vouchers, %d, counts.vouchercount); + + printf("\n"); + printf("total = %d\n", counts.total); + printf("SEND = %d\n", counts.sendcount); + printf("RECEIVE = %d\n", counts.receivecount); + printf("SEND_ONCE = %d\n", counts.sendoncecount); + printf("PORT_SET = %d\n", counts.portsetcount); + printf("DEAD_NAME = %d\n", counts.deadcount); + printf("DNREQUEST = %d\n", counts.dncount); + printf("VOUCHERS = %d\n", counts.vouchercount); +} + +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) { + int j, k, port_status_flag_idx; + kern_return_t ret; + boolean_t send = FALSE; + boolean_t dnreq = FALSE; + int sendrights = 0; + unsigned int kotype = 0; + vm_offset_t kobject = (vm_offset_t)0; + + /* skip empty slots in the table */ + if ((entry->iin_type & MACH_PORT_TYPE_ALL_RIGHTS) == 0) { + counts->total--; + return; + } + + if (entry->iin_type == MACH_PORT_TYPE_PORT_SET) { + mach_port_name_array_t members; + mach_msg_type_number_t membersCnt; + + ret = mach_port_get_set_status(taskinfo->task, + entry->iin_name, + &members, &membersCnt); + if (ret != KERN_SUCCESS) { + fprintf(stderr, "mach_port_get_set_status(0x%08x) failed: %s\n", + entry->iin_name, + mach_error_string(ret)); + return; } - - - if (taskinfo->table[i].iin_type == MACH_PORT_TYPE_PORT_SET) { - mach_port_name_array_t members; - mach_msg_type_number_t membersCnt; - - ret = mach_port_get_set_status(taskinfo->task, - taskinfo->table[i].iin_name, - &members, &membersCnt); - if (ret != KERN_SUCCESS) { - fprintf(stderr, "mach_port_get_set_status(0x%08x) failed: %s\n", - taskinfo->table[i].iin_name, - mach_error_string(ret)); - continue; - } - printf("0x%08x 0x%08x port-set -------- --- 1 %d members\n", - taskinfo->table[i].iin_name, - taskinfo->table[i].iin_object, - membersCnt); - /* get some info for each portset member */ - for (j = 0; j < membersCnt; j++) { - for (k = 0; k < taskinfo->tableCount; k++) { - if (taskinfo->table[k].iin_name == members[j]) { - mach_port_info_ext_t info; - mach_port_status_t port_status; - mach_port_context_t port_context = (mach_port_context_t)0; - if (0 != get_recieve_port_status(taskinfo->task, taskinfo->table[k].iin_name, &info)) { - bzero((void *)&info, sizeof(info)); + + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, type, "port set"); + JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object); + + JSON_KEY(json, members); + JSON_ARRAY_BEGIN(json); + + printf("0x%08x 0x%08x port-set -------- --- 1 %d members\n", + entry->iin_name, + entry->iin_object, + membersCnt); + /* get some info for each portset member */ + for (j = 0; j < membersCnt; j++) { + for (k = 0; k < taskinfo->tableCount; k++) { + if (taskinfo->table[k].iin_name == members[j]) { + mach_port_info_ext_t info; + mach_port_status_t port_status; + mach_port_context_t port_context = (mach_port_context_t)0; + if (0 != get_recieve_port_status(taskinfo->task, taskinfo->table[k].iin_name, &info)) { + bzero((void *)&info, sizeof(info)); + } + port_status = info.mpie_status; + get_receive_port_context(taskinfo->task, taskinfo->table[k].iin_name, &port_context); + + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", taskinfo->table[k].iin_object); + + JSON_KEY(json, rights); + JSON_ARRAY_BEGIN(json); + JSON_ARRAY_APPEND(json, "recv"); + if (taskinfo->table[k].iin_type & MACH_PORT_TYPE_SEND) { + JSON_ARRAY_APPEND(json, "send"); + } + JSON_ARRAY_END(json); // rights + + JSON_KEY(json, port_status_flags); + JSON_ARRAY_BEGIN(json); + port_status_flag_idx = 0; + while (0 != port_status_flags[port_status_flag_idx++].flag) { + if (port_status.mps_flags & INDEX_TO_PORT_FLAG(port_status_flag_idx)) { + JSON_ARRAY_APPEND(json, "%s", port_status_flags[port_status_flag_idx].name); } - port_status = info.mpie_status; - get_receive_port_context(taskinfo->task, taskinfo->table[k].iin_name, &port_context); - 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", - taskinfo->table[k].iin_object, - (taskinfo->table[k].iin_type & MACH_PORT_TYPE_SEND) ? "recv,send ":"recv ", - SHOW_PORT_STATUS_FLAGS(port_status.mps_flags), - info.mpie_boost_cnt, - (taskinfo->table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", - (port_status.mps_nsrequest) ? "N" : "-", - (port_status.mps_pdrequest) ? "P" : "-", - 1, - taskinfo->table[k].iin_urefs, - port_status.mps_sorights, - (port_status.mps_srights) ? "Y" : "N", - port_status.mps_qlimit, - port_status.mps_msgcount, - (uint64_t)port_context, - taskinfo->table[k].iin_name, - pid, - taskinfo->processName); - break; - } - } - } - - ret = vm_deallocate(mach_task_self(), (vm_address_t)members, - membersCnt * sizeof(mach_port_name_t)); - if (ret != KERN_SUCCESS) { - fprintf(stderr, "vm_deallocate() failed: %s\n", - mach_error_string(ret)); - exit(1); - } - portsetcount++; - continue; - } - - if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_SEND) { - send = TRUE; - sendrights = taskinfo->table[i].iin_urefs; - sendcount++; - } - - if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_DNREQUEST) { - dnreq = TRUE; - dncount++; - } - - if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_RECEIVE) { - mach_port_status_t status; - mach_port_info_ext_t info; - mach_port_context_t context = (mach_port_context_t)0; - ret = get_recieve_port_status(taskinfo->task, taskinfo->table[i].iin_name, &info); - get_receive_port_context(taskinfo->task, taskinfo->table[i].iin_name, &context); - /* its ok to fail in fetching attributes */ - if (ret < 0) { - continue; + } + JSON_ARRAY_END(json); // port status flags + JSON_OBJECT_SET(json, boosts, %d, info.mpie_boost_cnt); + + JSON_KEY(json, notifications); + JSON_ARRAY_BEGIN(json); + if (taskinfo->table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) { + JSON_ARRAY_APPEND(json, "dead name"); + } + if (port_status.mps_nsrequest) { + JSON_ARRAY_APPEND(json, "no sender"); + } + if (port_status.mps_nsrequest) { + JSON_ARRAY_APPEND(json, "port destroy request"); + } + JSON_ARRAY_END(json); // notifications + + JSON_OBJECT_SET(json, recv_rights, %d, 1); + JSON_OBJECT_SET(json, send_rights, %d, taskinfo->table[k].iin_urefs); + JSON_OBJECT_SET(json, send_once_rights, %d, port_status.mps_sorights); + JSON_OBJECT_SET_BOOL(json, oref, port_status.mps_srights); + JSON_OBJECT_SET(json, queue_limit, %d, port_status.mps_qlimit); + JSON_OBJECT_SET(json, msg_count, %d, port_status.mps_msgcount); + JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)port_context); + JSON_OBJECT_SET(json, identifier, "0x%08x", taskinfo->table[k].iin_name); + JSON_OBJECT_SET(json, pid, %d, taskinfo->pid); + JSON_OBJECT_SET(json, process, "%s", taskinfo->processName); + JSON_OBJECT_END(json); // member + + 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", + taskinfo->table[k].iin_object, + (taskinfo->table[k].iin_type & MACH_PORT_TYPE_SEND) ? "recv,send ":"recv ", + SHOW_PORT_STATUS_FLAGS(port_status.mps_flags), + info.mpie_boost_cnt, + (taskinfo->table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", + (port_status.mps_nsrequest) ? "N" : "-", + (port_status.mps_pdrequest) ? "P" : "-", + 1, + taskinfo->table[k].iin_urefs, + port_status.mps_sorights, + (port_status.mps_srights) ? "Y" : "N", + port_status.mps_qlimit, + port_status.mps_msgcount, + (uint64_t)port_context, + taskinfo->table[k].iin_name, + taskinfo->pid, + taskinfo->processName); + break; + } + } + } + + JSON_ARRAY_END(json); // members + JSON_OBJECT_END(json); // port-set + + ret = vm_deallocate(mach_task_self(), (vm_address_t)members, + membersCnt * sizeof(mach_port_name_t)); + if (ret != KERN_SUCCESS) { + fprintf(stderr, "vm_deallocate() failed: %s\n", + mach_error_string(ret)); + exit(1); + } + counts->portsetcount++; + return; + } + + if (entry->iin_type & MACH_PORT_TYPE_SEND) { + send = TRUE; + sendrights = entry->iin_urefs; + counts->sendcount++; + } + + if (entry->iin_type & MACH_PORT_TYPE_DNREQUEST) { + dnreq = TRUE; + counts->dncount++; + } + + if (entry->iin_type & MACH_PORT_TYPE_RECEIVE) { + mach_port_status_t status; + mach_port_info_ext_t info; + mach_port_context_t context = (mach_port_context_t)0; + struct k2n_table_node *k2nnode; + ret = get_recieve_port_status(taskinfo->task, entry->iin_name, &info); + get_receive_port_context(taskinfo->task, entry->iin_name, &context); + /* its ok to fail in fetching attributes */ + if (ret < 0) { + return; + } + status = info.mpie_status; + + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, type, "port"); + JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object); + + JSON_KEY(json, rights); + JSON_ARRAY_BEGIN(json); + JSON_ARRAY_APPEND(json, "recv"); + if (send) JSON_ARRAY_APPEND(json, "send"); + JSON_ARRAY_END(json); // rights + + JSON_KEY(json, port_status_flags); + JSON_ARRAY_BEGIN(json); + port_status_flag_idx = 0; + while (0 != port_status_flags[port_status_flag_idx++].flag) { + if (status.mps_flags & INDEX_TO_PORT_FLAG(port_status_flag_idx)) { + JSON_ARRAY_APPEND(json, "%s", port_status_flags[port_status_flag_idx].name); } - status = info.mpie_status; - 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", - taskinfo->table[i].iin_name, - taskinfo->table[i].iin_object, - (send) ? "recv,send ":"recv ", - SHOW_PORT_STATUS_FLAGS(status.mps_flags), - info.mpie_boost_cnt, - (dnreq) ? "D":"-", - (status.mps_nsrequest) ? "N":"-", - (status.mps_pdrequest) ? "P":"-", - 1, - sendrights, - status.mps_sorights, - (status.mps_srights) ? "Y":"N", - status.mps_qlimit, - status.mps_msgcount, - (uint64_t)context); - receivecount++; - - - /* show other rights (in this and other tasks) for the port */ - for (j = 0; j < taskCount; j++) { - for (k = 0; k < allTaskInfos[j].tableCount; k++) { - if (allTaskInfos[j].valid == FALSE || - &allTaskInfos[j].table[k] == &taskinfo->table[i] || - allTaskInfos[j].table[k].iin_object != taskinfo->table[i].iin_object) - continue; - + } + JSON_ARRAY_END(json); // port status flags + JSON_OBJECT_SET(json, boosts, %d, info.mpie_boost_cnt); + + JSON_KEY(json, notifications); + JSON_ARRAY_BEGIN(json); + if (dnreq) { + JSON_ARRAY_APPEND(json, "dead name"); + } + if (status.mps_nsrequest) { + JSON_ARRAY_APPEND(json, "no sender"); + } + if (status.mps_nsrequest) { + JSON_ARRAY_APPEND(json, "port destroy request"); + } + JSON_ARRAY_END(json); // notifications + + JSON_OBJECT_SET(json, recv_rights, %d, 1); + JSON_OBJECT_SET(json, send_rights, %d, sendrights); + JSON_OBJECT_SET(json, send_once_rights, %d, status.mps_sorights); + JSON_OBJECT_SET_BOOL(json, oref, status.mps_srights); + JSON_OBJECT_SET(json, queue_limit, %d, status.mps_qlimit); + JSON_OBJECT_SET(json, msg_count, %d, status.mps_msgcount); + JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)context); + JSON_OBJECT_END(json); // port + + 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", + entry->iin_name, + entry->iin_object, + (send) ? "recv,send ":"recv ", + SHOW_PORT_STATUS_FLAGS(status.mps_flags), + info.mpie_boost_cnt, + (dnreq) ? "D":"-", + (status.mps_nsrequest) ? "N":"-", + (status.mps_pdrequest) ? "P":"-", + 1, + sendrights, + status.mps_sorights, + (status.mps_srights) ? "Y":"N", + status.mps_qlimit, + status.mps_msgcount, + (uint64_t)context); + counts->receivecount++; + + /* show other rights (in this and other tasks) for the port */ + for (j = 0; j < taskCount; j++) { + if (allTaskInfos[j].valid == FALSE) + continue; + + k2nnode = k2n_table_lookup(allTaskInfos[j].k2ntable, entry->iin_object); + + while (k2nnode) { + if (k2nnode->info_name != entry) { + assert(k2nnode->info_name->iin_object == entry->iin_object); + printf(" + %s -------- %s%s%s %5d <- 0x%08x (%d) %s\n", - (allTaskInfos[j].table[k].iin_type & MACH_PORT_TYPE_SEND_ONCE) ? - "send-once " : "send ", - (allTaskInfos[j].table[k].iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", + (k2nnode->info_name->iin_type & MACH_PORT_TYPE_SEND_ONCE) ? + "send-once " : "send ", + (k2nnode->info_name->iin_type & MACH_PORT_TYPE_DNREQUEST) ? "D" : "-", "-", "-", - allTaskInfos[j].table[k].iin_urefs, - allTaskInfos[j].table[k].iin_name, - allTaskInfos[j].pid, + k2nnode->info_name->iin_urefs, + k2nnode->info_name->iin_name, + allTaskInfos[j].pid, allTaskInfos[j].processName); - } - } - continue; - } - else if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_DEAD_NAME) - { - printf("0x%08x 0x%08x dead-name -------- --- %5d \n", - taskinfo->table[i].iin_name, - taskinfo->table[i].iin_object, - taskinfo->table[i].iin_urefs); - deadcount++; - continue; - } - - if (taskinfo->table[i].iin_type & MACH_PORT_TYPE_SEND_ONCE) { - sendonce = TRUE; - sendoncecount++; - } - - printf("0x%08x 0x%08x %s -------- %s%s%s %5.0d ", - taskinfo->table[i].iin_name, - taskinfo->table[i].iin_object, - (send) ? "send ":"send-once ", - (dnreq) ? "D":"-", - "-", - "-", - (send) ? sendrights : 0); - - /* converting to kobjects is not always supported */ - ret = mach_port_kernel_object(taskinfo->task, - taskinfo->table[i].iin_name, - &kotype, (unsigned *)&kobject); - if (ret == KERN_SUCCESS && kotype != 0) { - printf(" 0x%08x %s", (natural_t)kobject, kobject_name(kotype)); - if ((kotype == IKOT_TASK_RESUME) || (kotype == IKOT_TASK) || (kotype == IKOT_TASK_NAME)) { - if (taskinfo->task_kobject == kobject) { - /* neat little optimization since in most cases tasks have themselves in their ipc space */ - printf(" SELF (%d) %s", taskinfo->pid, taskinfo->processName); - } else { - my_per_task_info_t * _found_task = get_taskinfo_by_kobject((natural_t)kobject); - printf(" (%d) %s", _found_task->pid, _found_task->processName); } + + k2nnode = k2n_table_lookup_next(k2nnode, entry->iin_object); } - - printf("\n"); - if (kotype == IKOT_VOUCHER) { - vouchercount++; - if (lsmp_config.show_voucher_details) { - char * detail = copy_voucher_detail(taskinfo->task, taskinfo->table[i].iin_name); - printf("%s\n", detail); - free(detail); - } + } + return; + } + else if (entry->iin_type & MACH_PORT_TYPE_DEAD_NAME) + { + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, type, "dead name"); + JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object); + JSON_OBJECT_SET(json, send_rights, %d, entry->iin_urefs); + JSON_OBJECT_END(json); // dead name + + printf("0x%08x 0x%08x dead-name -------- --- %5d \n", + entry->iin_name, + entry->iin_object, + entry->iin_urefs); + counts->deadcount++; + return; + } + + if (entry->iin_type & MACH_PORT_TYPE_SEND_ONCE) { + counts->sendoncecount++; + } + + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, name, "0x%08x", entry->iin_name); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", entry->iin_object); + + JSON_KEY(json, rights); + JSON_ARRAY_BEGIN(json); + JSON_ARRAY_APPEND(json, "%s", (send) ? "send":"send once"); + JSON_ARRAY_END(json); //rights + + JSON_KEY(json, notifications); + JSON_ARRAY_BEGIN(json); + if (dnreq) JSON_ARRAY_APPEND(json, "dead name"); + JSON_ARRAY_END(json); // notifications + + JSON_OBJECT_SET(json, send_rights, %d, (send) ? sendrights : 0); + + printf("0x%08x 0x%08x %s -------- %s%s%s %5.0d ", + entry->iin_name, + entry->iin_object, + (send) ? "send ":"send-once ", + (dnreq) ? "D":"-", + "-", + "-", + (send) ? sendrights : 0); + + /* converting to kobjects is not always supported */ + ret = mach_port_kernel_object(taskinfo->task, + entry->iin_name, + &kotype, (unsigned *)&kobject); + if (ret == KERN_SUCCESS && kotype != 0) { + JSON_OBJECT_SET(json, identifier, "0x%08x", (natural_t)kobject); + JSON_OBJECT_SET(json, type, "%s", kobject_name(kotype)); + printf(" 0x%08x %s", (natural_t)kobject, kobject_name(kotype)); + if ((kotype == IKOT_TASK_RESUME) || (kotype == IKOT_TASK) || (kotype == IKOT_TASK_NAME)) { + if (taskinfo->task_kobject == kobject) { + /* neat little optimization since in most cases tasks have themselves in their ipc space */ + JSON_OBJECT_SET(json, pid, %d, taskinfo->pid); + JSON_OBJECT_SET(json, process, "%s", taskinfo->processName); + printf(" SELF (%d) %s", taskinfo->pid, taskinfo->processName); + } else { + my_per_task_info_t * _found_task = get_taskinfo_by_kobject((natural_t)kobject); + JSON_OBJECT_SET(json, pid, %d, _found_task->pid); + JSON_OBJECT_SET(json, process, "%s", _found_task->processName); + printf(" (%d) %s", _found_task->pid, _found_task->processName); } - continue; - } - - /* not kobject - find the receive right holder */ - my_per_task_info_t *recv_holder_taskinfo; - mach_port_name_t recv_name = MACH_PORT_NULL; - if (KERN_SUCCESS == get_taskinfo_of_receiver_by_send_right(&taskinfo->table[i], &recv_holder_taskinfo, &recv_name)) { - mach_port_status_t port_status; - mach_port_info_ext_t info; - mach_port_context_t port_context = (mach_port_context_t)0; - if (0 != get_recieve_port_status(recv_holder_taskinfo->task, recv_name, &info)) { - bzero((void *)&port_status, sizeof(port_status)); + } + + if (kotype == IKOT_THREAD) { + for (int i = 0; i < taskinfo->threadCount; i++) { + if (taskinfo->threadInfos[i].th_kobject == kobject) { + printf(" (%#llx)", taskinfo->threadInfos[i].th_id); + break; + } + } + } + + printf("\n"); + if (kotype == IKOT_VOUCHER) { + counts->vouchercount++; + if (lsmp_config.show_voucher_details) { + JSON_KEY(json, recipes); + JSON_ARRAY_BEGIN(json); + char * detail = copy_voucher_detail(taskinfo->task, entry->iin_name, json); + JSON_ARRAY_END(json); // recipes + printf("%s\n", detail); + free(detail); } - port_status = info.mpie_status; - get_receive_port_context(recv_holder_taskinfo->task, recv_name, &port_context); - printf(" -> %6d %8d 0x%016llx 0x%08x (%d) %s\n", - port_status.mps_qlimit, - port_status.mps_msgcount, - (uint64_t)port_context, - recv_name, - recv_holder_taskinfo->pid, - recv_holder_taskinfo->processName); - - } else - printf(" 0x00000000 (-) Unknown Process\n"); - - } - printf("total = %d\n", taskinfo->tableCount + taskinfo->treeCount - emptycount); - printf("SEND = %d\n", sendcount); - printf("RECEIVE = %d\n", receivecount); - printf("SEND_ONCE = %d\n", sendoncecount); - printf("PORT_SET = %d\n", portsetcount); - printf("DEAD_NAME = %d\n", deadcount); - printf("DNREQUEST = %d\n", dncount); - printf("VOUCHERS = %d\n", vouchercount); - + } + JSON_OBJECT_END(json); // kobject + return; + } + + /* not kobject - find the receive right holder */ + my_per_task_info_t *recv_holder_taskinfo; + mach_port_name_t recv_name = MACH_PORT_NULL; + if (KERN_SUCCESS == get_taskinfo_of_receiver_by_send_right(entry, &recv_holder_taskinfo, &recv_name)) { + mach_port_status_t port_status; + mach_port_info_ext_t info; + mach_port_context_t port_context = (mach_port_context_t)0; + if (0 != get_recieve_port_status(recv_holder_taskinfo->task, recv_name, &info)) { + bzero((void *)&port_status, sizeof(port_status)); + } + port_status = info.mpie_status; + get_receive_port_context(recv_holder_taskinfo->task, recv_name, &port_context); + + JSON_OBJECT_SET(json, queue_limit, %d, port_status.mps_qlimit); + JSON_OBJECT_SET(json, msg_count, %d, port_status.mps_msgcount); + JSON_OBJECT_SET(json, context, "0x%016llx", (uint64_t)port_context); + JSON_OBJECT_SET(json, identifier, "0x%08x", recv_name); + JSON_OBJECT_SET(json, pid, %d, recv_holder_taskinfo->pid); + JSON_OBJECT_SET(json, process, "%s", recv_holder_taskinfo->processName); + + printf(" -> %6d %8d 0x%016llx 0x%08x (%d) %s\n", + port_status.mps_qlimit, + port_status.mps_msgcount, + (uint64_t)port_context, + recv_name, + recv_holder_taskinfo->pid, + recv_holder_taskinfo->processName); + + } else { + JSON_OBJECT_SET(json, identifier, "0x%08x", 0); + JSON_OBJECT_SET(json, pid, %d, -1); + JSON_OBJECT_SET(json, process, "unknown"); + printf(" 0x00000000 (-) Unknown Process\n"); + } + + JSON_OBJECT_END(json); // non-kobject } -void print_hex_data(char *outstr, size_t maxlen, char *prefix, char *desc, void *addr, int len) { +uint32_t print_hex_data(char *outstr, uint32_t maxlen, char *prefix, char *desc, void *addr, int len) { int i; unsigned char buff[17]; unsigned char *pc = addr; uint32_t plen = 0; - + if (desc != NULL) - plen += safesize(snprintf(&outstr[len], maxlen - plen, "%s%s:\n", prefix, desc)); - + plen += snprintf(&outstr[plen], safesize(maxlen - plen), "%s%s:\n", prefix, desc); + for (i = 0; i < len; i++) { - + if ((i % 16) == 0) { if (i != 0) - plen += safesize(snprintf(&outstr[len], maxlen - plen, " %s\n", buff)); - - plen += safesize(snprintf(&outstr[len], maxlen - plen, "%s %04x ", prefix, i)); + plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %s\n", buff); + + plen += snprintf(&outstr[plen], safesize(maxlen - plen), "%s %04x ", prefix, i); } - - plen += safesize(snprintf(&outstr[len], maxlen - plen, " %02x", pc[i])); - + + plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %02x", pc[i]); + if ((pc[i] < 0x20) || (pc[i] > 0x7e)) buff[i % 16] = '.'; else buff[i % 16] = pc[i]; buff[(i % 16) + 1] = '\0'; } - + while ((i % 16) != 0) { - plen += safesize(snprintf(&outstr[len], maxlen - plen, " ")); + plen += snprintf(&outstr[plen], safesize(maxlen - plen), " "); i++; } - - plen += safesize(snprintf(&outstr[len], maxlen - plen, " %s\n", buff)); + + plen += snprintf(&outstr[plen], safesize(maxlen - plen), " %s\n", buff); + + return plen; }