2015-01-14 02:37:10 +00:00
|
|
|
#include "threads_darwin.h"
|
|
|
|
|
|
|
|
int
|
|
|
|
write_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
|
|
|
|
kern_return_t kret;
|
|
|
|
pointer_t data;
|
|
|
|
memcpy((void *)&data, d, len);
|
|
|
|
|
|
|
|
// Set permissions to enable writting to this memory location
|
|
|
|
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY);
|
|
|
|
if (kret != KERN_SUCCESS) return -1;
|
|
|
|
|
|
|
|
kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)&data, len);
|
|
|
|
if (kret != KERN_SUCCESS) return -1;
|
|
|
|
|
|
|
|
// Restore virtual memory permissions
|
|
|
|
// TODO(dp) this should take into account original permissions somehow
|
|
|
|
kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
|
|
|
|
if (kret != KERN_SUCCESS) return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
read_memory(mach_port_name_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) {
|
|
|
|
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);
|
2015-02-28 16:35:44 +00:00
|
|
|
|
|
|
|
kret = vm_deallocate(task, data, len);
|
|
|
|
if (kret != KERN_SUCCESS) return -1;
|
|
|
|
|
2015-01-14 02:37:10 +00:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2015-02-28 16:39:21 +00:00
|
|
|
kern_return_t
|
|
|
|
get_registers(mach_port_name_t task, x86_thread_state64_t *state) {
|
2015-01-14 02:37:10 +00:00
|
|
|
kern_return_t kret;
|
|
|
|
mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;
|
|
|
|
|
|
|
|
// TODO(dp) - possible memory leak - vm_deallocate state
|
2015-02-28 16:39:21 +00:00
|
|
|
return thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)state, &stateCount);
|
2015-01-14 02:37:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(dp) this should return kret instead of void
|
2015-02-28 16:41:05 +00:00
|
|
|
kern_return_t
|
2015-01-14 02:37:10 +00:00
|
|
|
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);
|
2015-02-28 16:41:05 +00:00
|
|
|
if (kret != KERN_SUCCESS) return kret;
|
2015-01-14 02:37:10 +00:00
|
|
|
state.__rip = pc;
|
|
|
|
|
|
|
|
// TODO(dp) - possible memory leak - vm_deallocate state
|
2015-02-28 16:41:05 +00:00
|
|
|
return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount);
|
2015-01-14 02:37:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO(dp) this should return kret instead of void
|
|
|
|
void
|
|
|
|
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)®s, &count);
|
|
|
|
if (kret != KERN_SUCCESS) {
|
|
|
|
puts("get state fail");
|
|
|
|
puts(mach_error_string(kret));
|
|
|
|
}
|
|
|
|
// Set trap bit in rflags
|
|
|
|
regs.__rflags |= 0x100UL;
|
|
|
|
|
|
|
|
kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count);
|
|
|
|
if (kret != KERN_SUCCESS) {
|
|
|
|
puts("set state fail");
|
|
|
|
puts(mach_error_string(kret));
|
|
|
|
}
|
|
|
|
// TODO(dp) vm deallocate state?
|
|
|
|
|
|
|
|
// Continue here until we've fully decremented suspend_count
|
|
|
|
for (;;) {
|
|
|
|
kret = thread_resume(thread);
|
|
|
|
if (kret != KERN_SUCCESS) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-27 21:27:48 +00:00
|
|
|
// TODO(dp) return kret
|
2015-01-14 02:37:10 +00:00
|
|
|
void
|
|
|
|
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)®s, &count);
|
|
|
|
if (kret != KERN_SUCCESS) {
|
|
|
|
puts("get state fail");
|
|
|
|
puts(mach_error_string(kret));
|
|
|
|
}
|
|
|
|
// Clear trap bit in rflags
|
|
|
|
regs.__rflags ^= 0x100UL;
|
|
|
|
|
|
|
|
kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count);
|
|
|
|
if (kret != KERN_SUCCESS) {
|
|
|
|
puts("set state fail");
|
|
|
|
puts(mach_error_string(kret));
|
|
|
|
}
|
|
|
|
// TODO(dp) vm deallocate state?
|
|
|
|
}
|