gitlab.com/Raven-IO/raven-delve@v1.22.4/pkg/proc/native/threads_darwin.c (about) 1 //+build darwin,macnative 2 3 #include "threads_darwin.h" 4 5 int 6 write_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) { 7 kern_return_t kret; 8 vm_region_submap_short_info_data_64_t info; 9 mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; 10 mach_vm_size_t l = len; 11 mach_port_t objname; 12 13 if (len == 1) l = 2; 14 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); 15 if (kret != KERN_SUCCESS) return -1; 16 17 // Set permissions to enable writing to this memory location 18 kret = mach_vm_protect(task, addr, len, FALSE, VM_PROT_WRITE|VM_PROT_COPY|VM_PROT_READ); 19 if (kret != KERN_SUCCESS) return -1; 20 21 kret = mach_vm_write((vm_map_t)task, addr, (vm_offset_t)d, len); 22 if (kret != KERN_SUCCESS) return -1; 23 24 // Restore virtual memory permissions 25 kret = mach_vm_protect(task, addr, len, FALSE, info.protection); 26 if (kret != KERN_SUCCESS) return -1; 27 28 return 0; 29 } 30 31 int 32 read_memory(task_t task, mach_vm_address_t addr, void *d, mach_msg_type_number_t len) { 33 kern_return_t kret; 34 pointer_t data; 35 mach_msg_type_number_t count; 36 37 kret = mach_vm_read((vm_map_t)task, addr, len, &data, &count); 38 if (kret != KERN_SUCCESS) return -1; 39 memcpy(d, (void *)data, len); 40 41 kret = vm_deallocate(task, data, len); 42 if (kret != KERN_SUCCESS) return -1; 43 44 return count; 45 } 46 47 kern_return_t 48 get_registers(mach_port_name_t task, x86_thread_state64_t *state) { 49 kern_return_t kret; 50 mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; 51 // TODO(dp) - possible memory leak - vm_deallocate state 52 return thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)state, &stateCount); 53 } 54 55 kern_return_t 56 get_fpu_registers(mach_port_name_t task, x86_float_state64_t *state) { 57 kern_return_t kret; 58 mach_msg_type_number_t stateCount = x86_FLOAT_STATE64_COUNT; 59 return thread_get_state(task, x86_FLOAT_STATE64, (thread_state_t)state, &stateCount); 60 } 61 62 kern_return_t 63 get_identity(mach_port_name_t task, thread_identifier_info_data_t *idinfo) { 64 mach_msg_type_number_t idinfoCount = THREAD_IDENTIFIER_INFO_COUNT; 65 return thread_info(task, THREAD_IDENTIFIER_INFO, (thread_info_t)idinfo, &idinfoCount); 66 } 67 68 kern_return_t 69 set_registers(mach_port_name_t task, x86_thread_state64_t *state) { 70 mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; 71 return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)state, stateCount); 72 } 73 74 kern_return_t 75 set_pc(thread_act_t task, uint64_t pc) { 76 kern_return_t kret; 77 x86_thread_state64_t state; 78 mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT; 79 80 kret = thread_get_state(task, x86_THREAD_STATE64, (thread_state_t)&state, &stateCount); 81 if (kret != KERN_SUCCESS) return kret; 82 state.__rip = pc; 83 84 return thread_set_state(task, x86_THREAD_STATE64, (thread_state_t)&state, stateCount); 85 } 86 87 kern_return_t 88 single_step(thread_act_t thread) { 89 kern_return_t kret; 90 x86_thread_state64_t regs; 91 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 92 93 kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, &count); 94 if (kret != KERN_SUCCESS) return kret; 95 96 // Set trap bit in rflags 97 regs.__rflags |= 0x100UL; 98 99 kret = thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count); 100 if (kret != KERN_SUCCESS) return kret; 101 102 return resume_thread(thread); 103 } 104 105 kern_return_t 106 resume_thread(thread_act_t thread) { 107 kern_return_t kret; 108 struct thread_basic_info info; 109 unsigned int info_count = THREAD_BASIC_INFO_COUNT; 110 111 kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); 112 if (kret != KERN_SUCCESS) return kret; 113 114 for (int i = 0; i < info.suspend_count; i++) { 115 kret = thread_resume(thread); 116 if (kret != KERN_SUCCESS) return kret; 117 } 118 return KERN_SUCCESS; 119 } 120 121 kern_return_t 122 clear_trap_flag(thread_act_t thread) { 123 kern_return_t kret; 124 x86_thread_state64_t regs; 125 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 126 127 kret = thread_get_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, &count); 128 if (kret != KERN_SUCCESS) return kret; 129 130 // Clear trap bit in rflags 131 regs.__rflags ^= 0x100UL; 132 133 return thread_set_state(thread, x86_THREAD_STATE64, (thread_state_t)®s, count); 134 } 135 136 int 137 thread_blocked(thread_act_t thread) { 138 kern_return_t kret; 139 struct thread_basic_info info; 140 unsigned int info_count = THREAD_BASIC_INFO_COUNT; 141 142 kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); 143 if (kret != KERN_SUCCESS) return -1; 144 145 return info.suspend_count; 146 } 147 148 int 149 num_running_threads(task_t task) { 150 kern_return_t kret; 151 thread_act_array_t list; 152 mach_msg_type_number_t count; 153 int i, n = 0; 154 155 kret = task_threads(task, &list, &count); 156 if (kret != KERN_SUCCESS) { 157 return -kret; 158 } 159 160 for (i = 0; i < count; ++i) { 161 thread_act_t thread = list[i]; 162 struct thread_basic_info info; 163 unsigned int info_count = THREAD_BASIC_INFO_COUNT; 164 165 kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count); 166 167 if (kret == KERN_SUCCESS) { 168 if (info.suspend_count == 0) { 169 ++n; 170 } else { 171 } 172 } 173 } 174 175 kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0])); 176 if (kret != KERN_SUCCESS) return -kret; 177 178 return n; 179 }