X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/ac27e6b4e9f2f269ad11856171ae8e1f51fa26f0..887d5eedc67e1d6b5933393070e765bc7739453c:/lsmp.tproj/task_details.c diff --git a/lsmp.tproj/task_details.c b/lsmp.tproj/task_details.c index bb490f2..e8b1ffe 100644 --- a/lsmp.tproj/task_details.c +++ b/lsmp.tproj/task_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@ * @@ -27,9 +27,62 @@ #include #include #include +#include #include "common.h" +#pragma mark kobject to name hash table implementation + +#if (K2N_TABLE_SIZE & (K2N_TABLE_SIZE - 1) != 0) +#error K2N_TABLE_SIZE must be a power of two +#endif + +#define K2N_TABLE_MASK (K2N_TABLE_SIZE - 1) + +static uint32_t k2n_hash(natural_t kobject) { + return (uint64_t)kobject * 2654435761 >> 32; +} + +struct k2n_table_node *k2n_table_lookup_next(struct k2n_table_node *node, natural_t kobject) { + while (node) { + if (kobject == node->kobject) + return node; + + node = node->next; + } + + return NULL; +} + +struct k2n_table_node *k2n_table_lookup(struct k2n_table_node **table, natural_t kobject) { + uint32_t hv; + struct k2n_table_node *node; + + hv = k2n_hash(kobject); + + node = table[hv & K2N_TABLE_MASK]; + + return k2n_table_lookup_next(node, kobject); +} + +static void k2n_table_enter(struct k2n_table_node **table, natural_t kobject, ipc_info_name_t *info_name) { + uint32_t hv; + struct k2n_table_node *node; + + hv = k2n_hash(kobject); + + node = malloc(sizeof (struct k2n_table_node)); + assert(node); + + node->kobject = kobject; + node->info_name = info_name; + + node->next = table[hv & K2N_TABLE_MASK]; + table[hv & K2N_TABLE_MASK] = node; +} + +#pragma mark - + static my_per_task_info_t NOT_FOUND_TASK_INFO = { .task = NULL, .task_kobject = NULL, @@ -40,6 +93,7 @@ static my_per_task_info_t NOT_FOUND_TASK_INFO = { .tree = NULL, .treeCount = 0, .valid = FALSE, + .k2ntable = {0}, .processName = "Unknown", .exceptionInfo = {0}, .threadInfos = NULL, @@ -79,10 +133,11 @@ void deallocate_taskinfo_memory(my_per_task_info_t *data){ kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_t target_task) { + int i; kern_return_t ret = KERN_SUCCESS; unsigned int kotype = 0; vm_offset_t kobject = (vm_offset_t)0; - + taskinfo->task = target_task; pid_for_task(target_task, &taskinfo->pid); @@ -136,7 +191,7 @@ kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_t target_ } if (KERN_SUCCESS == thread_get_mach_voucher(threadPorts[i], 0, &th_voucher) && th_voucher != IPC_VOUCHER_NULL) { - char *detail = copy_voucher_detail(mach_task_self(), th_voucher); + char *detail = copy_voucher_detail(mach_task_self(), th_voucher, NULL); taskinfo->threadInfos[i].voucher_detail = strndup(detail, VOUCHER_DETAIL_MAXLEN); free(detail); @@ -156,33 +211,36 @@ kern_return_t collect_per_task_info(my_per_task_info_t *taskinfo, task_t target_ vm_deallocate(mach_task_self(), threadPorts, taskinfo->threadCount * sizeof(thread_act_t)); threadPorts = NULL; - + ret = mach_port_space_info(target_task, &taskinfo->info, &taskinfo->table, &taskinfo->tableCount, &taskinfo->tree, &taskinfo->treeCount); - + if (ret != KERN_SUCCESS) { fprintf(stderr, "mach_port_space_info() failed: pid:%d error: %s\n",taskinfo->pid, mach_error_string(ret)); taskinfo->pid = 0; return ret; } - + + bzero(taskinfo->k2ntable, K2N_TABLE_SIZE * sizeof (struct k2n_table_node *)); + for (i = 0; i < taskinfo->tableCount; i++) { + k2n_table_enter(taskinfo->k2ntable, taskinfo->table[i].iin_object, &taskinfo->table[i]); + } + proc_pid_to_name(taskinfo->pid, taskinfo->processName); ret = mach_port_kernel_object(mach_task_self(), taskinfo->task, &kotype, (unsigned *)&kobject); - + if (ret == KERN_SUCCESS && kotype == IKOT_TASK) { taskinfo->task_kobject = kobject; taskinfo->valid = TRUE; } - + return ret; } - - void get_exc_behavior_string(exception_behavior_t b, char *out_string, size_t len) { out_string[0]='\0'; - + if (b & MACH_EXCEPTION_CODES) strncat(out_string, "MACH +", len); switch (b & ~MACH_EXCEPTION_CODES) { @@ -203,7 +261,7 @@ void get_exc_behavior_string(exception_behavior_t b, char *out_string, size_t le void get_exc_mask_string(exception_mask_t m, char *out_string, size_t len) { out_string[0]='\0'; - + if (m & (1<exceptionInfo.count; i++) { if (taskinfo->exceptionInfo.ports[i] != MACH_PORT_NULL) { @@ -247,45 +307,67 @@ kern_return_t print_task_exception_info(my_per_task_info_t *taskinfo) } get_exc_behavior_string(taskinfo->exceptionInfo.behaviors[i], behavior_string, sizeof(behavior_string)); get_exc_mask_string(taskinfo->exceptionInfo.masks[i], mask_string, 200); + + JSON_OBJECT_BEGIN(json); + JSON_OBJECT_SET(json, port, "0x%08x", taskinfo->exceptionInfo.ports[i]); + JSON_OBJECT_SET(json, flavor, "0x%03x", taskinfo->exceptionInfo.flavors[i]); + JSON_OBJECT_SET(json, behavior, "%s", behavior_string); + JSON_OBJECT_SET(json, mask, "%s", mask_string); + JSON_OBJECT_END(json); // exception port + printf(" 0x%08x 0x%03x <%s> %s \n" , taskinfo->exceptionInfo.ports[i], taskinfo->exceptionInfo.flavors[i], behavior_string, mask_string); } - + } - + + JSON_ARRAY_END(json); // exception ports + return KERN_SUCCESS; } -kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) +kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo, JSON_t json) { kern_return_t kret = KERN_SUCCESS; mach_msg_type_number_t threadcount = taskinfo->threadCount; boolean_t header_required = TRUE; boolean_t newline_required = TRUE; struct my_per_thread_info * info = NULL; - + + JSON_KEY(json, threads); + JSON_ARRAY_BEGIN(json); + for (int i = 0; i < threadcount; i++) { + JSON_OBJECT_BEGIN(json); + info = &taskinfo->threadInfos[i]; if (header_required) { printf("Thread_KObject Thread-ID Port Description."); header_required = FALSE; } - + if (newline_required) { printf("\n"); } newline_required = TRUE; - + if (info->th_kobject != 0) { /* TODO: Should print tid and stuff */ printf("0x%08x ", info->th_kobject); printf("0x%llx ", info->th_id); + + JSON_OBJECT_SET(json, kobject, "0x%08x", info->th_kobject); + JSON_OBJECT_SET(json, tid, "0x%llx", info->th_id); } if (info->voucher_detail != NULL) { + /* TODO: include voucher detail in JSON */ printf("%s\n", info->voucher_detail); } + JSON_KEY(json, exception_ports); + JSON_ARRAY_BEGIN(json); + /* print the thread exception ports also */ if (taskinfo->threadExceptionInfos != NULL) { @@ -297,6 +379,8 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) if (excinfo->count > 0) { boolean_t header_required = TRUE; for (int i = 0; i < excinfo->count; i++) { + JSON_OBJECT_BEGIN(json); + if (excinfo->ports[i] != MACH_PORT_NULL) { if (header_required) { printf("\n exc_port flavor mask -> name owner\n"); @@ -304,6 +388,12 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) } get_exc_behavior_string(excinfo->behaviors[i], behavior_string, sizeof(behavior_string)); get_exc_mask_string(excinfo->masks[i], mask_string, sizeof(mask_string)); + + JSON_OBJECT_SET(json, port, "0x%08x", excinfo->ports[i]); + JSON_OBJECT_SET(json, flavor, "0x%03x", excinfo->flavors[i]); + JSON_OBJECT_SET(json, behavior, "%s", behavior_string); + JSON_OBJECT_SET(json, mask, "%s", mask_string); + printf(" 0x%08x 0x%03x <%s> %s " , excinfo->ports[i], excinfo->flavors[i], behavior_string, mask_string); ipc_info_name_t actual_sendinfo; @@ -311,6 +401,12 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) 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(&actual_sendinfo, &recv_holder_taskinfo, &recv_name)) { + + JSON_OBJECT_SET(json, name, "0x%08x", recv_name); + JSON_OBJECT_SET(json, ipc-object, "0x%08x", actual_sendinfo.iin_object); + JSON_OBJECT_SET(json, pid, %d, recv_holder_taskinfo->pid); + JSON_OBJECT_SET(json, process, "%s", recv_holder_taskinfo->processName); + printf(" -> 0x%08x 0x%08x (%d) %s\n", recv_name, actual_sendinfo.iin_object, @@ -325,13 +421,15 @@ kern_return_t print_task_threads_special_ports(my_per_task_info_t *taskinfo) printf("\n"); } - + JSON_OBJECT_END(json); // exception port } } - } - + JSON_ARRAY_END(json); // exception ports + JSON_OBJECT_END(json); // thread } + + JSON_ARRAY_END(json); // threads printf("\n"); return kret; } @@ -359,22 +457,22 @@ my_per_task_info_t * get_taskinfo_by_kobject(natural_t kobj) { kern_return_t get_taskinfo_of_receiver_by_send_right(ipc_info_name_t *sendright, my_per_task_info_t **out_taskinfo, mach_port_name_t *out_recv_info) { - kern_return_t retval = KERN_FAILURE; - boolean_t found = FALSE; *out_taskinfo = &NOT_FOUND_TASK_INFO; - - for (int j = 0; j < global_taskcount && !found; j++) { - for (int k = 0; k < global_taskinfo[j].tableCount && !found; k++) { - if ((global_taskinfo[j].table[k].iin_type & MACH_PORT_TYPE_RECEIVE) && - global_taskinfo[j].table[k].iin_object == sendright->iin_object ) { + struct k2n_table_node *k2nnode; + + for (int j = 0; j < global_taskcount; j++) { + if ((k2nnode = k2n_table_lookup(global_taskinfo[j].k2ntable, sendright->iin_object))) { + assert(k2nnode->info_name->iin_object == sendright->iin_object); + + if (k2nnode->info_name->iin_type & MACH_PORT_TYPE_RECEIVE) { *out_taskinfo = &global_taskinfo[j]; - *out_recv_info = global_taskinfo[j].table[k].iin_name; - found = TRUE; - retval = KERN_SUCCESS; + *out_recv_info = k2nnode->info_name->iin_name; + return KERN_SUCCESS; } } } - return retval; + + return KERN_FAILURE; } kern_return_t get_ipc_info_from_lsmp_spaceinfo(mach_port_t port_name, ipc_info_name_t *out_sendright){ @@ -399,5 +497,3 @@ kern_return_t get_ipc_info_from_lsmp_spaceinfo(mach_port_t port_name, ipc_info_n return retval; } - -