static void PrintPortSetMembers(mach_port_t taskSendRight, mach_port_name_t portSetName) // For a given Mach port set within a given task, print the members // of the port set. { kern_return_t err; kern_return_t junk; mach_port_name_array_t memberNames; mach_msg_type_number_t memberNamesCount; mach_msg_type_number_t memberIndex; memberNames = NULL; // Get an array of members. err = mach_port_get_set_status( taskSendRight, portSetName, &memberNames, &memberNamesCount ); // Iterate over the array, printing each one. Note that we print 6 members to // a line and we start every line except the second with enough spaces to // account for the information that we print that's common to each type // of output. if (err == KERN_SUCCESS) { fprintf(stdout, " "); for (memberIndex = 0; memberIndex < memberNamesCount; memberIndex++) { if ( (memberIndex != 0) && (memberIndex % 6) == 0) { // 6 columns of (8 characters plus space) // plus DNR column (3 chars) plus space fprintf(stdout, "\n%*s ", (6 * (8 + 1)) + 3 + 1, ""); } fprintf(stdout, "%#8x ", memberNames[memberIndex]); } } else { fprintf(stdout, "??? "); } // Clean up. if (memberNames != NULL) { junk = vm_deallocate(mach_task_self(), (vm_address_t) memberNames, memberNamesCount * sizeof(*memberNames)); assert(junk == KERN_SUCCESS); } }
void mportset_callback(void) { mach_port_name_array_t members; mach_msg_type_number_t membersCnt; mach_port_status_t status; mach_msg_type_number_t statusCnt; struct kevent kev; unsigned int i; if (os_assumes_zero(mach_port_get_set_status(mach_task_self(), demand_port_set, &members, &membersCnt)) != 0) { return; } for (i = 0; i < membersCnt; i++) { statusCnt = MACH_PORT_RECEIVE_STATUS_COUNT; if (mach_port_get_attributes(mach_task_self(), members[i], MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status, &statusCnt) != KERN_SUCCESS) { continue; } if (status.mps_msgcount) { EV_SET(&kev, members[i], EVFILT_MACHPORT, 0, 0, 0, job_find_by_service_port(members[i])); #if 0 if (kev.udata != NULL) { #endif log_kevent_struct(LOG_DEBUG, &kev, 0); (*((kq_callback *)kev.udata))(kev.udata, &kev); #if 0 } else { log_kevent_struct(LOG_ERR, &kev, 0); } #endif /* the callback may have tainted our ability to continue this for loop */ break; } } (void)os_assumes_zero(vm_deallocate(mach_task_self(), (vm_address_t)members, (vm_size_t) membersCnt * sizeof(mach_port_name_t))); }
void show_task_mach_ports(my_per_task_info_t *taskinfo, uint32_t taskCount, my_per_task_info_t *allTaskInfos) { 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); 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; } 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)); } 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; } 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->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; 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" : "-", "-", "-", allTaskInfos[j].table[k].iin_urefs, allTaskInfos[j].table[k].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); } } printf("\n"); if (kotype == IKOT_VOUCHER) { vouchercount++; if (lsmp_config.show_voucher_details) { show_voucher_detail(taskinfo->task, taskinfo->table[i].iin_name); } } 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)); } 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); }