threads_darwin.c 5.1 KB
Newer Older
D
Derek Parker 已提交
1 2 3
#include "threads_darwin.h"

int
4
write_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
D
Derek Parker 已提交
5
	kern_return_t kret;
6 7 8 9 10 11
	vm_region_submap_short_info_data_64_t info;
	mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
	mach_vm_size_t l = len;
	mach_port_t objname;

	if (len == 1) l = 2;
D
Derek Parker 已提交
12
	kret = mach_vm_region((vm_map_t)task, &(mach_vm_address_t){addr}, (mach_vm_size_t*)&l, VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info, &count, &objname);
13 14
	if (kret != KERN_SUCCESS) return -1;

D
Derek Parker 已提交
15
	// Set permissions to enable writting to this memory location
D
Derek Parker 已提交
16
	kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_WRITE|VM_PROT_COPY|VM_PROT_READ);
D
Derek Parker 已提交
17 18
	if (kret != KERN_SUCCESS) return -1;

19
	kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)d, len);
D
Derek Parker 已提交
20 21 22
	if (kret != KERN_SUCCESS) return -1;

	// Restore virtual memory permissions
23 24 25
	kret = mach_vm_protect(task, addr, len, FALSE, info.protection);
	if (kret != KERN_SUCCESS) return -1;

D
Derek Parker 已提交
26 27 28 29
	return 0;
}

int
30
read_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
D
Derek Parker 已提交
31 32 33 34 35 36 37
	kern_return_t kret;
	pointer_t data;
	mach_msg_type_number_t count;

	kret = mach_vm_read((vm_map_t)task, addr, len, &data, &count);
	if (kret != KERN_SUCCESS) return -1;
	memcpy(d, (void *)data, len);
D
Derek Parker 已提交
38 39 40 41

	kret = vm_deallocate(task, data, len);
	if (kret != KERN_SUCCESS) return -1;

D
Derek Parker 已提交
42 43 44
	return count;
}

D
Derek Parker 已提交
45 46
kern_return_t
get_registers(mach_port_name_t task, x86_thread_state64_t *state) {
D
Derek Parker 已提交
47 48 49
	kern_return_t kret;
	mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
	// TODO(dp) - possible memory leak - vm_deallocate state
D
Derek Parker 已提交
50
	return thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)state, &stateCount);
D
Derek Parker 已提交
51 52
}

A
aarzilli 已提交
53 54 55 56 57 58 59
kern_return_t
get_fpu_registers(mach_port_name_t task, x86_float_state64_t *state) {
	kern_return_t kret;
	mach_msg_type_number_t stateCount = x86_FLOAT_STATE64_COUNT;
	return thread_get_state(task, x86_FLOAT_STATE64, (thread_state_t)state, &stateCount);
}

60 61 62 63 64 65
kern_return_t
get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) {
	mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT;
	return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount);
}

D
Derek Parker 已提交
66 67 68 69 70 71
kern_return_t
set_registers(mach_port_name_t task, x86_thread_state64_t *state) {
	mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
	return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)state, stateCount);
}

D
Derek Parker 已提交
72
kern_return_t
D
Derek Parker 已提交
73 74 75 76 77 78
set_pc(thread_act_t task, uint64_t pc) {
	kern_return_t kret;
	x86_thread_state64_t state;
	mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;

	kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount);
D
Derek Parker 已提交
79
	if (kret != KERN_SUCCESS) return kret;
D
Derek Parker 已提交
80 81
	state.__rip = pc;

D
Derek Parker 已提交
82
	return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount);
D
Derek Parker 已提交
83 84
}

85
kern_return_t
D
Derek Parker 已提交
86 87 88 89 90 91
single_step(thread_act_t thread) {
	kern_return_t kret;
	x86_thread_state64_t regs;
	mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;

	kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, &count);
92 93
	if (kret != KERN_SUCCESS) return kret;

D
Derek Parker 已提交
94 95 96 97
	// Set trap bit in rflags
	regs.__rflags |= 0x100UL;

	kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, count);
98
	if (kret != KERN_SUCCESS) return kret;
D
Derek Parker 已提交
99

100
	return resume_thread(thread);
101 102 103 104 105
}

kern_return_t
resume_thread(thread_act_t thread) {
	kern_return_t kret;
D
Derek Parker 已提交
106
	struct thread_basic_info info;
107 108
	unsigned int info_count = THREAD_BASIC_INFO_COUNT;

D
Derek Parker 已提交
109
	kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count);
110 111 112
	if (kret != KERN_SUCCESS) return kret;

	for (int i = 0; i < info.suspend_count; i++) {
D
Derek Parker 已提交
113
		kret = thread_resume(thread);
114
		if (kret != KERN_SUCCESS) return kret;
D
Derek Parker 已提交
115
	}
116
	return KERN_SUCCESS;
D
Derek Parker 已提交
117 118
}

119
kern_return_t
D
Derek Parker 已提交
120 121 122 123 124 125
clear_trap_flag(thread_act_t thread) {
	kern_return_t kret;
	x86_thread_state64_t regs;
	mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;

	kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, &count);
126 127
	if (kret != KERN_SUCCESS) return kret;

D
Derek Parker 已提交
128 129 130
	// Clear trap bit in rflags
	regs.__rflags ^= 0x100UL;

131
	return thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)&regs, count);
D
Derek Parker 已提交
132
}
133 134 135 136 137 138 139 140 141 142 143 144

int
thread_blocked(thread_act_t thread) {
	kern_return_t kret;
	struct thread_basic_info info;
	unsigned int info_count = THREAD_BASIC_INFO_COUNT;

	kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count);
	if (kret != KERN_SUCCESS) return -1;

	return info.suspend_count;
}
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

int
num_running_threads(task_t task) {
	kern_return_t kret;
	thread_act_array_t list;
	mach_msg_type_number_t count;
	int i, n = 0;

	kret = task_threads(task, &list, &count);
	if (kret != KERN_SUCCESS) {
		return -kret;
	}

	for (i = 0; i < count; ++i) {
		thread_act_t thread = list[i];
		struct thread_basic_info info;
		unsigned int info_count = THREAD_BASIC_INFO_COUNT;

		kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count);

		if (kret == KERN_SUCCESS) {
			if (info.suspend_count == 0) {
				++n;
			} else {
			}
		}
	}

	kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0]));
	if (kret != KERN_SUCCESS) return -kret;

	return n;
}