/ duct-tape / src / debug.c
debug.c
  1  #include <darlingserver/duct-tape.h>
  2  #include <darlingserver/duct-tape/task.h>
  3  
  4  uint64_t dtape_debug_task_port_count(dtape_task_t* task) {
  5  	return task->xnu_task.itk_space->is_table_hashed;
  6  };
  7  
  8  uint64_t dtape_debug_task_list_ports(dtape_task_t* task, dtape_debug_task_list_ports_iterator_f iterator, void* context) {
  9  	uint64_t port_count = 0;
 10  	bool call_it = true;
 11  
 12  	for (mach_port_index_t index = 0; index < task->xnu_task.itk_space->is_table_size; ++index) {
 13  		ipc_entry_t entry = &task->xnu_task.itk_space->is_table[index];
 14  		dtape_debug_port_t debug_port;
 15  		ipc_port_t port = NULL;
 16  
 17  		if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE) {
 18  			continue;
 19  		}
 20  
 21  		port = ip_object_to_port(entry->ie_object);
 22  
 23  		debug_port.name = MACH_PORT_MAKE(index, IE_BITS_GEN(entry->ie_bits));
 24  		debug_port.refs = IE_BITS_UREFS(entry->ie_bits);
 25  		debug_port.rights = IE_BITS_TYPE(entry->ie_bits);
 26  		debug_port.messages = port->ip_messages.imq_msgcount;
 27  
 28  		if (call_it) {
 29  			call_it = iterator(context, &debug_port);
 30  		}
 31  
 32  		++port_count;
 33  	}
 34  
 35  	return port_count;
 36  };
 37  
 38  uint64_t dtape_debug_portset_list_members(dtape_task_t* task, uint32_t portset, dtape_debug_portset_list_members_iterator_f iterator, void* context) {
 39  	ipc_object_t object = NULL;
 40  	ipc_mqueue_t mqueue = NULL;
 41  	ipc_entry_num_t member_count = 0;
 42  	mach_port_name_t* names = NULL;
 43  	ipc_entry_num_t actual_count = 0;
 44  	bool call_it = true;
 45  
 46  	if (ipc_mqueue_copyin(task->xnu_task.itk_space, portset, &mqueue, &object) != KERN_SUCCESS) {
 47  		return 0;
 48  	}
 49  
 50  	do {
 51  		if (names) {
 52  			kfree(names, sizeof(*names) * member_count);
 53  		}
 54  
 55  		names = kalloc(sizeof(*names) * actual_count);
 56  		member_count = actual_count;
 57  
 58  		ipc_mqueue_set_gather_member_names(task->xnu_task.itk_space, mqueue, member_count, names, &actual_count);
 59  	} while (member_count != actual_count);
 60  
 61  	for (ipc_entry_num_t i = 0; i < member_count; ++i) {
 62  		mach_port_name_t* name = &names[i];
 63  		dtape_debug_port_t debug_port;
 64  		ipc_entry_t entry = NULL;
 65  		ipc_port_t port = NULL;
 66  
 67  		entry = ipc_entry_lookup(task->xnu_task.itk_space, *name);
 68  		port = ip_object_to_port(entry->ie_object);
 69  
 70  		debug_port.name = *name;
 71  		debug_port.refs = IE_BITS_UREFS(entry->ie_bits);
 72  		debug_port.rights = IE_BITS_TYPE(entry->ie_bits);
 73  		debug_port.messages = port->ip_messages.imq_msgcount;
 74  
 75  		if (call_it) {
 76  			call_it = iterator(context, &debug_port);
 77  		}
 78  	}
 79  
 80  	if (names) {
 81  		kfree(names, sizeof(*names) * member_count);
 82  	}
 83  
 84  	io_release(object);
 85  
 86  	return member_count;
 87  };
 88  
 89  uint64_t dtape_debug_port_list_messages(dtape_task_t* task, uint32_t port, dtape_debug_port_list_messages_iterator_f iterator, void* context) {
 90  	ipc_object_t object = NULL;
 91  	ipc_mqueue_t mqueue = NULL;
 92  	uint64_t message_count = 0;
 93  	bool call_it = true;
 94  
 95  	if (ipc_mqueue_copyin(task->xnu_task.itk_space, port, &mqueue, &object) != KERN_SUCCESS) {
 96  		return 0;
 97  	}
 98  
 99  	for (ipc_kmsg_t kmsg = ipc_kmsg_queue_first(&mqueue->imq_messages); kmsg != NULL; kmsg = ipc_kmsg_queue_next(&mqueue->imq_messages, kmsg)) {
100  		dtape_debug_message_t debug_message;
101  
102  		debug_message.sender = 0;
103  
104  		if (kmsg->ikm_header->msgh_remote_port && kmsg->ikm_header->msgh_remote_port->ip_receiver) {
105  			debug_message.sender = dtape_task_for_xnu_task(kmsg->ikm_header->msgh_remote_port->ip_receiver->is_task)->saved_pid;
106  		}
107  
108  		debug_message.size = kmsg->ikm_size;
109  
110  		if (call_it) {
111  			call_it = iterator(context, &debug_message);
112  		}
113  
114  		++message_count;
115  	}
116  
117  	io_release(object);
118  
119  	return message_count;
120  };