this repo has no description
at fixPythonPipStalling 600 lines 20 kB view raw
1#include <darling/emulation/common/simple.h> 2#include <unistd.h> 3#include <dlfcn.h> 4#include <mach/message.h> 5#include <mach/mach_time.h> 6#include <mach/mig_errors.h> 7#include <servers/bootstrap.h> 8#include <pthread.h> 9 10 11#include "xtracelib.h" 12#include "mach_trace.h" 13#include "mig_trace.h" 14#include "tls.h" 15#include "string.h" 16 17DEFINE_XTRACE_TLS_VAR(int, mach_call_nr, -1, NULL); 18DEFINE_XTRACE_TLS_VAR(void*, argument_ptr, NULL, NULL); 19DEFINE_XTRACE_TLS_VAR(mach_port_name_t, request_port, MACH_PORT_NULL, NULL); 20 21static void print_kern_return(xtrace::String* log, int nr, uintptr_t rv); 22static void print_port_return(xtrace::String* log, int nr, uintptr_t rv); 23static void print_int_return(xtrace::String* log, int nr, uintptr_t rv); 24static void print_empty(xtrace::String* log, int nr, void* args[]); 25static void print_port_ptr_return(xtrace::String* log, int nr, uintptr_t rv); 26 27static void print_mach_msg_args(xtrace::String* log, int nr, void* args[]); 28static void print_mach_port_insert_right_args(xtrace::String* log, int nr, void* args[]); 29 30static void print_mach_port_member_args(xtrace::String* log, int nr, void* args[]); 31 32static void print_mach_timebase_info_args(xtrace::String* log, int nr, void* args[]); 33static void print_mach_timebase_info_res(xtrace::String* log, int nr, uintptr_t rv); 34 35static void print_mach_port_allocate_args(xtrace::String* log, int nr, void* args[]); 36static void print_task_for_pid_args(xtrace::String* log, int nr, void* args[]); 37 38static void print_pid_for_task_args(xtrace::String* log, int nr, void* args[]); 39static void print_pid_for_task_res(xtrace::String* log, int nr, uintptr_t rv); 40 41static void print_mach_msg_entry(xtrace::String* log, void* args[]); 42static void print_mach_msg_exit(xtrace::String* log); 43 44static const struct calldef mach_defs[128] = { 45 [10] = { "_kernelrpc_mach_vm_allocate_trap", NULL, print_kern_return }, 46 [12] = { "_kernelrpc_mach_vm_deallocate_trap", NULL, print_kern_return }, 47 [14] = { "_kernelrpc_mach_vm_protect_trap", NULL, print_kern_return }, 48 [15] = { "_kernelrpc_mach_vm_map_trap", NULL, print_kern_return }, 49 [16] = { "_kernelrpc_mach_port_allocate_trap", print_mach_port_allocate_args, print_port_ptr_return }, 50 [17] = { "_kernelrpc_mach_port_destroy_trap", NULL, print_kern_return }, 51 [18] = { "_kernelrpc_mach_port_deallocate_trap", [](xtrace::String* log, int nr, void* args[]) { log->append_format("task %u, port name %u", (unsigned int) (unsigned long) args[0], (unsigned int) (unsigned long) args[1]); }, print_kern_return }, 52 [19] = { "_kernelrpc_mach_port_mod_refs_trap", NULL, print_kern_return }, 53 [20] = { "_kernelrpc_mach_port_move_member_trap", print_mach_port_member_args, print_kern_return }, 54 [21] = { "_kernelrpc_mach_port_insert_right_trap", print_mach_port_insert_right_args, print_kern_return }, 55 [22] = { "_kernelrpc_mach_port_insert_member_trap", print_mach_port_member_args, print_kern_return }, 56 [23] = { "_kernelrpc_mach_port_extract_member_trap", print_mach_port_member_args, print_kern_return }, 57 [24] = { "_kernelrpc_mach_port_construct_trap", NULL, print_kern_return }, 58 [25] = { "_kernelrpc_mach_port_destruct_trap", NULL, print_kern_return }, 59 [26] = { "mach_reply_port", print_empty, print_port_return }, 60 [27] = { "thread_self_trap", print_empty, print_port_return }, 61 [28] = { "task_self_trap", print_empty, print_port_return }, 62 [29] = { "host_self_trap", print_empty, print_port_return }, 63 [31] = { "mach_msg_trap", print_mach_msg_args, print_kern_return }, 64 [32] = { "mach_msg_overwrite_trap", print_mach_msg_args, print_kern_return }, 65 [33] = { "semaphore_signal_trap", NULL, print_kern_return }, 66 [34] = { "semaphore_signal_all_trap", NULL, print_kern_return }, 67 [35] = { "semaphore_signal_thread_trap", NULL, print_kern_return }, 68 [36] = { "semaphore_wait_trap", NULL, print_kern_return }, 69 [37] = { "semaphore_wait_signal_trap", NULL, print_kern_return }, 70 [38] = { "semaphore_timedwait_trap", NULL, print_kern_return }, 71 [39] = { "semaphore_timedwait_signal_trap", NULL, print_kern_return }, 72 [41] = { "_kernelrpc_mach_port_guard_trap", NULL, print_kern_return }, 73 [42] = { "_kernelrpc_mach_port_unguard_trap", NULL, print_kern_return }, 74 [43] = { "mach_generate_activity_id", NULL, print_kern_return }, 75 [44] = { "task_name_for_pid", print_task_for_pid_args, print_port_ptr_return }, 76 [45] = { "task_for_pid", print_task_for_pid_args, print_port_ptr_return }, 77 [46] = { "pid_for_task", print_pid_for_task_args, print_pid_for_task_res }, 78 [48] = { "macx_swapon", NULL, print_kern_return }, 79 [49] = { "macx_swapoff", NULL, print_kern_return }, 80 [51] = { "macx_triggers", NULL, print_kern_return }, 81 [52] = { "macx_backing_store_suspend", NULL, print_kern_return }, 82 [53] = { "macx_backing_store_recovery", NULL, print_kern_return }, 83 [59] = { "swtch_pri", NULL, print_kern_return }, 84 [60] = { "swtch", NULL, print_kern_return }, 85 [61] = { "syscall_thread_switch", NULL, print_kern_return }, 86 [62] = { "clock_sleep_trap", NULL, print_kern_return }, 87 [89] = { "mach_timebase_info_trap", print_mach_timebase_info_args, print_mach_timebase_info_res }, 88 [90] = { "mach_wait_until", NULL, print_kern_return }, 89 [91] = { "mk_timer_create", print_empty, print_port_return }, 90 [92] = { "mk_timer_destroy", NULL, print_kern_return }, 91 [93] = { "mk_timer_arm", NULL, print_kern_return }, 92 [94] = { "mk_timer_cancel", NULL, print_kern_return }, 93}; 94 95static const char* const kern_return_values[] = { 96 "KERN_SUCCESS", 97 "KERN_INVALID_ADDRESS", 98 "KERN_PROTECTION_FAILURE", 99 "KERN_NO_SPACE", 100 "KERN_INVALID_ARGUMENT", 101 "KERN_FAILURE", 102 "KERN_RESOURCE_SHORTAGE", 103 "KERN_NOT_RECEIVER", 104 "KERN_NO_ACCESS", 105 "KERN_MEMORY_FAILURE", 106 "KERN_MEMORY_ERROR", 107 "KERN_ALREADY_IN_SET", 108 "KERN_NOT_IN_SET", 109 "KERN_NAME_EXISTS", 110 "KERN_ABORTED", 111 "KERN_INVALID_NAME", 112 "KERN_INVALID_TASK", 113 "KERN_INVALID_RIGHT", 114 "KERN_INVALID_VALUE", 115 "KERN_UREFS_OVERFLOW", 116 "KERN_INVALID_CAPABILITY", 117 "KERN_RIGHT_EXISTS", 118 "KERN_INVALID_HOST", 119 "KERN_MEMORY_PRESENT", 120 "KERN_MEMORY_DATA_MOVED", 121 "KERN_MEMORY_RESTART_COPY", 122 "KERN_INVALID_PROCESSOR_SET", 123 "KERN_POLICY_LIMIT", 124 "KERN_INVALID_POLICY", 125 "KERN_INVALID_OBJECT", 126 "KERN_ALREADY_WAITING", 127 "KERN_DEFAULT_SET", 128 "KERN_EXCEPTION_PROTECTED", 129 "KERN_INVALID_LEDGER", 130 "KERN_INVALID_MEMORY_CONTROL", 131 "KERN_INVALID_SECURITY", 132 "KERN_NOT_DEPRESSED", 133 "KERN_TERMINATED", 134 "KERN_LOCK_SET_DESTROYED", 135 "KERN_LOCK_UNSTABLE", 136 "KERN_LOCK_OWNED", 137 "KERN_LOCK_OWNED_SELF", 138 "KERN_SEMAPHORE_DESTROYED", 139 "KERN_RPC_SERVER_TERMINATED", 140 "KERN_RPC_TERMINATE_ORPHAN", 141 "KERN_RPC_CONTINUE_ORPHAN", 142 "KERN_NOT_SUPPORTED", 143 "KERN_NODE_DOWN", 144 "KERN_NOT_WAITING", 145 "KERN_OPERATION_TIMED_OUT", 146 "KERN_CODESIGN_ERROR", 147 "KERN_POLICY_STATIC", 148 "KERN_INSUFFICIENT_BUFFER_SIZE", 149}; 150 151static const char* const mach_send_errors[] = { 152 "MACH_SEND_IN_PROGRESS", 153 "MACH_SEND_INVALID_DATA", 154 "MACH_SEND_INVALID_DEST", 155 "MACH_SEND_TIMED_OUT", 156 "MACH_SEND_INTERRUPTED", 157 "MACH_SEND_MSG_TOO_SMALL", 158 "MACH_SEND_INVALID_REPLY", 159 "MACH_SEND_INVALID_RIGHT", 160 "MACH_SEND_INVALID_NOTIFY", 161 "MACH_SEND_INVALID_MEMORY", 162 "MACH_SEND_NO_BUFFER", 163 "MACH_SEND_TOO_LARGE", 164 "MACH_SEND_INVALID_TYPE", 165 "MACH_SEND_INVALID_HEADER", 166 "MACH_SEND_INVALID_TRAILER" 167}; 168 169static const char* const mach_rcv_errors[] = { 170 "MACH_RCV_IN_PROGRESS", 171 "MACH_RCV_INVALID_NAME", 172 "MACH_RCV_TIMED_OUT", 173 "MACH_RCV_TOO_LARGE", 174 "MACH_RCV_INTERRUPTED", 175 "MACH_RCV_PORT_CHANGED", 176 "MACH_RCV_INVALID_NOTIFY", 177 "MACH_RCV_INVALID_DATA", 178 "MACH_RCV_PORT_DIED", 179 "MACH_RCV_IN_SET", 180 "MACH_RCV_HEADER_ERROR", 181 "MACH_RCV_BODY_ERROR", 182 "MACH_RCV_INVALID_TYPE", 183 "MACH_RCV_SCATTER_SMALL", 184 "MACH_RCV_INVALID_TRAILER" 185}; 186 187static const char* const mig_errors[] = { 188 "MIG_TYPE_ERROR", 189 "MIG_REPLY_MISMATCH", 190 "MIG_REMOTE_ERROR", 191 "MIG_BAD_ID", 192 "MIG_BAD_ARGUMENTS", 193 "MIG_NO_REPLY", 194 "MIG_EXCEPTION", 195 "MIG_ARRAY_TOO_LARGE", 196 "MIG_SERVER_DIED", 197 "MIG_TRAILER_ERROR" 198}; 199 200static const char* const bootstrap_errors[] = { 201 "BOOTSTRAP_NOT_PRIVILEGED", 202 "BOOTSTRAP_NAME_IN_USE", 203 "BOOTSTRAP_UNKNOWN_SERVICE", 204 "BOOTSTRAP_SERVICE_ACTIVE", 205 "BOOTSTRAP_BAD_COUNT", 206 "BOOTSTRAP_NO_MEMORY", 207 "BOOTSTRAP_NO_CHILDREN" 208}; 209 210extern "C" 211void darling_mach_syscall_entry_print(int nr, void* args[]) 212{ 213 xtrace::String log; 214#if __i386__ 215 // get rid of some info in the upper bytes that we don't need 216 nr = (int)((unsigned int)nr & 0xffff); 217#endif 218 219 set_mach_call_nr(nr); 220 handle_generic_entry(&log, mach_defs, "mach", nr, args); 221 if (nr == 31 || nr == 32) 222 print_mach_msg_entry(&log, args); 223 224 if (log.size() > 0) { 225 xtrace_log("%s", log.c_str()); 226 log.clear(); 227 } 228} 229 230extern "C" 231void darling_mach_syscall_exit_print(uintptr_t retval) 232{ 233 xtrace::String log; 234 int nr = get_mach_call_nr(); 235 int is_msg = nr == 31 || nr == 32; 236 handle_generic_exit(&log, mach_defs, "mach", retval, is_msg); 237 if (retval == KERN_SUCCESS && is_msg) 238 print_mach_msg_exit(&log); 239 set_mach_call_nr(-1); 240 241 if (log.size() > 0) { 242 xtrace_log("%s", log.c_str()); 243 log.clear(); 244 } 245} 246 247void xtrace_print_kern_return(xtrace::String* log, kern_return_t kr) 248{ 249 if (kr >= MACH_RCV_IN_PROGRESS && kr <= MACH_RCV_INVALID_TRAILER) 250 log->append_format("%s", mach_rcv_errors[kr - MACH_RCV_IN_PROGRESS]); 251 else if (kr >= MACH_SEND_IN_PROGRESS && kr <= MACH_SEND_INVALID_TRAILER) 252 log->append_format("%s", mach_send_errors[kr - MACH_SEND_IN_PROGRESS]); 253 else if (kr >= KERN_SUCCESS && kr <= KERN_INSUFFICIENT_BUFFER_SIZE) 254 log->append_format("%s", kern_return_values[kr]); 255 else if (kr >= BOOTSTRAP_NOT_PRIVILEGED && kr <= BOOTSTRAP_NO_CHILDREN) 256 log->append_format("%s", bootstrap_errors[kr - BOOTSTRAP_NOT_PRIVILEGED]); 257 else if (kr <= MIG_TYPE_ERROR && kr >= MIG_TRAILER_ERROR) 258 log->append_format("%s", mig_errors[MIG_TYPE_ERROR - kr]); 259 else 260 log->append_format("(kern_return_t) %x", kr); 261} 262 263static void print_kern_return(xtrace::String* log, int nr, uintptr_t rv) 264{ 265 xtrace_print_kern_return(log, (kern_return_t) rv); 266} 267 268static void print_port_return(xtrace::String* log, int nr, uintptr_t rv) 269{ 270 log->append_format("port right %d", (unsigned int) (unsigned long) rv); 271} 272 273static void print_int_return(xtrace::String* log, char* buf, int nr, uintptr_t rv) 274{ 275 log->append_format("%d", (int) (long) rv); 276} 277 278static void print_empty(xtrace::String* log, int nr, void* args[]) 279{ 280 281} 282 283static void print_port_ptr_return(xtrace::String* log, int nr, uintptr_t rv) 284{ 285 if (rv != KERN_SUCCESS) 286 { 287 print_kern_return(log, nr, rv); 288 set_argument_ptr(NULL); 289 return; 290 } 291 if (get_argument_ptr() == NULL) 292 { 293 return; 294 } 295 log->append_format("port right %d", *(mach_port_name_t*)get_argument_ptr()); 296 set_argument_ptr(NULL); 297} 298 299 300static const char* const port_right_names[] = { 301 "MACH_PORT_RIGHT_SEND", 302 "MACH_PORT_RIGHT_RECEIVE", 303 "MACH_PORT_RIGHT_SEND_ONCE", 304 "MACH_PORT_RIGHT_PORT_SET", 305 "MACH_PORT_RIGHT_DEAD_NAME", 306 "MACH_PORT_RIGHT_NUMBER" 307}; 308 309static void print_mach_port_allocate_args(xtrace::String* log, int nr, void* args[]) 310{ 311 mach_port_name_t target = (mach_port_name_t) (long) args[0]; 312 mach_port_right_t right = (mach_port_right_t) (long) args[1]; 313 set_argument_ptr(args[2]); 314 315 const char* right_name; 316 if (right > MACH_PORT_RIGHT_NUMBER) 317 right_name = "unknown"; 318 else 319 right_name = port_right_names[right]; 320 321 log->append_format("task %d, %s", target, right_name); 322} 323 324static const char* const port_dispositions[] = { 325 "MACH_MSG_TYPE_PORT_NAME", 326 "MACH_MSG_TYPE_MOVE_RECEIVE", 327 "MACH_MSG_TYPE_MOVE_SEND", 328 "MACH_MSG_TYPE_MOVE_SEND_ONCE", 329 "MACH_MSG_TYPE_COPY_SEND", 330 "MACH_MSG_TYPE_MAKE_SEND", 331 "MACH_MSG_TYPE_MAKE_SEND_ONCE", 332 "MACH_MSG_TYPE_COPY_RECEIVE", 333 "MACH_MSG_TYPE_DISPOSE_RECEIVE", 334 "MACH_MSG_TYPE_DISPOSE_SEND", 335 "MACH_MSG_TYPE_DISPOSE_SEND_ONCE" 336}; 337 338static void print_mach_port_insert_right_args(xtrace::String* log, int nr, void* args[]) 339{ 340 mach_port_name_t target = (mach_port_name_t) (long) args[0]; 341 mach_port_name_t name = (mach_port_name_t) (long) args[1]; 342 mach_port_name_t right = (mach_port_name_t) (long) args[2]; 343 mach_msg_type_name_t disposition = (mach_msg_type_name_t) (long) args[3]; 344 345 const char* disp; 346 if (disposition > MACH_MSG_TYPE_DISPOSE_SEND_ONCE || disposition < MACH_MSG_TYPE_PORT_NAME) 347 disp = "unknown"; 348 else 349 disp = port_dispositions[disposition - MACH_MSG_TYPE_PORT_NAME]; 350 351 log->append_format("task %d, new name %d, port right %d, %s", target, name, right, disp); 352} 353 354static void print_mach_port_member_args(xtrace::String* log, int nr, void* args[]) 355{ 356 mach_port_name_t target = (mach_port_name_t) (long) args[0]; 357 mach_port_name_t name = (mach_port_name_t) (long) args[1]; 358 mach_port_name_t pset = (mach_port_name_t) (long) args[2]; 359 360 log->append_format("task %d, port right %d, port set %d", target, name, pset); 361} 362 363static void print_mach_timebase_info_args(xtrace::String* log, int nr, void* args[]) 364{ 365 set_argument_ptr(args[0]); 366 if (get_argument_ptr() == NULL) 367 log->append("NULL"); 368} 369 370static void print_mach_timebase_info_res(xtrace::String* log, int nr, uintptr_t rv) 371{ 372 if (rv != KERN_SUCCESS) 373 { 374 print_kern_return(log, nr, rv); 375 set_argument_ptr(NULL); 376 return; 377 } 378 if (get_argument_ptr() != NULL) 379 { 380 mach_timebase_info_t timebase = (mach_timebase_info_t)get_argument_ptr(); 381 log->append_format("numer = %d, denom = %d", timebase->numer, timebase->denom); 382 } 383 384 set_argument_ptr(NULL); 385} 386 387static void print_task_for_pid_args(xtrace::String* log, int nr, void* args[]) 388{ 389 mach_port_name_t target = (mach_port_name_t) (long) args[0]; 390 int pid = (int) (long) args[1]; 391 set_argument_ptr(args[2]); 392 393 log->append_format("task %d, pid %d", target, pid); 394} 395 396static void print_pid_for_task_args(xtrace::String* log, int nr, void* args[]) 397{ 398 mach_port_name_t task = (mach_port_name_t) (long) args[0]; 399 set_argument_ptr(args[1]); 400 401 log->append_format("task %d", task); 402} 403 404static void print_pid_for_task_res(xtrace::String* log, int nr, uintptr_t rv) 405{ 406 if (rv != KERN_SUCCESS) 407 { 408 print_kern_return(log, nr, rv); 409 set_argument_ptr(NULL); 410 return; 411 } 412 if (get_argument_ptr() != NULL) 413 log->append_format("pid %d", * (int*)get_argument_ptr()); 414 415 set_argument_ptr(NULL); 416} 417 418const char* xtrace_msg_type_to_str(mach_msg_type_name_t type_name, int full) 419{ 420 switch (type_name) 421 { 422 case MACH_MSG_TYPE_MOVE_RECEIVE: 423 return full ? "MACH_MSG_TYPE_MOVE_RECEIVE" : "move recv"; 424 case MACH_MSG_TYPE_MOVE_SEND: 425 return full ? "MACH_MSG_TYPE_MOVE_SEND" : "move send"; 426 case MACH_MSG_TYPE_COPY_SEND: 427 return full ? "MACH_MSG_TYPE_COPY_SEND" : "copy send"; 428 case MACH_MSG_TYPE_MAKE_SEND: 429 return full ? "MACH_MSG_TYPE_MAKE_SEND" : "make send"; 430 case MACH_MSG_TYPE_MOVE_SEND_ONCE: 431 return full ? "MACH_MSG_TYPE_MOVE_SEND_ONCE" : "move send-once"; 432 case MACH_MSG_TYPE_MAKE_SEND_ONCE: 433 return full ? "MACH_MSG_TYPE_MAKE_SEND_ONCE" : "make send-once"; 434 default: 435 return "unknown"; 436 } 437} 438 439static void print_mach_msg(xtrace::String* log, const mach_msg_header_t* msg, mach_msg_size_t size) 440{ 441 log->append("{"); 442 443 mach_msg_bits_t bits = msg->msgh_bits; 444 if (MACH_MSGH_BITS_HAS_REMOTE(bits)) 445 log->append_format("remote = %s %u, ", xtrace_msg_type_to_str(MACH_MSGH_BITS_REMOTE(bits), 0), msg->msgh_remote_port); 446 if (MACH_MSGH_BITS_HAS_LOCAL(bits)) 447 log->append_format("local = %s %u, ", xtrace_msg_type_to_str(MACH_MSGH_BITS_LOCAL(bits), 0), msg->msgh_local_port); 448 if (MACH_MSGH_BITS_HAS_VOUCHER(bits)) 449 log->append_format("voucher = %s %u, ", xtrace_msg_type_to_str(MACH_MSGH_BITS_VOUCHER(bits), 0), msg->msgh_voucher_port); 450 if (MACH_MSGH_BITS_IS_COMPLEX(bits)) 451 log->append("complex, "); 452 453 log->append_format("id = %d}", msg->msgh_id); 454 455 if (!MACH_MSGH_BITS_IS_COMPLEX(bits)) 456 { 457 log->append_format(", %lu bytes of inline data", size - sizeof(mach_msg_header_t)); 458 xtrace_log("%s\n", log->c_str()); 459 log->clear(); 460 return; 461 } 462 463 mach_msg_body_t* body = (mach_msg_body_t*) (msg + 1); 464 mach_msg_size_t descriptor_count = body->msgh_descriptor_count; 465 mach_msg_descriptor_t* ptr = (mach_msg_descriptor_t*) (body + 1); 466 for (mach_msg_size_t i = 0; i < descriptor_count; i++) 467 { 468 mach_msg_descriptor_type_t type = ((mach_msg_type_descriptor_t*) ptr)->type; 469 if (type == MACH_MSG_PORT_DESCRIPTOR) 470 { 471 mach_msg_port_descriptor_t* port = (mach_msg_port_descriptor_t*) ptr; 472 log->append_format(", %s %u", xtrace_msg_type_to_str(port->disposition, 0), port->name); 473 ptr = (mach_msg_descriptor_t*) (port + 1); 474 } 475 else if (type == MACH_MSG_OOL_DESCRIPTOR || type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) 476 { 477 mach_msg_ool_descriptor_t* ool = (mach_msg_ool_descriptor_t*) ptr; 478 log->append_format(", ool [%p; %u]", ool->address, ool->size); 479 ptr = (mach_msg_descriptor_t*) (ool + 1); 480 } 481 else if (type == MACH_MSG_OOL_PORTS_DESCRIPTOR) 482 { 483 mach_msg_ool_ports_descriptor_t* ool_ports = (mach_msg_ool_ports_descriptor_t*) ptr; 484 log->append_format(", ool ports %s [%p; x%u]", 485 xtrace_msg_type_to_str(ool_ports->disposition, 0), 486 ool_ports->address, ool_ports->count); 487 ptr = (mach_msg_descriptor_t*) (ool_ports + 1); 488 } 489 else 490 { 491 log->append(", ???"); 492 ptr++; 493 } 494 } 495 496 log->append_format(", %lu bytes of inline data", size - ((const char*) ptr - (const char*) msg)); 497 xtrace_log("%s\n", log->c_str()); 498 log->clear(); 499} 500 501static void print_mach_msg_entry(xtrace::String* log, void* args[]) 502{ 503 const mach_msg_header_t* message = (const mach_msg_header_t*) args[0]; 504 mach_msg_option_t options = (mach_msg_option_t) (long) args[1]; 505 mach_msg_size_t send_size = (mach_msg_size_t) (unsigned long) args[2]; 506 507 if (options & MACH_SEND_MSG) 508 { 509 set_request_port(message->msgh_remote_port); 510 xtrace_log("%s\n", log->c_str()); log->clear(); 511 xtrace_start_line(log, 8); 512 print_mach_msg(log, message, send_size); 513 xtrace_start_line(log, 8); 514 xtrace_print_mig_message(log, message, get_request_port()); 515 xtrace_log("%s\n", log->c_str()); log->clear(); 516 } 517 518 if (options & MACH_RCV_MSG) 519 { 520 switch (get_mach_call_nr()) 521 { 522 case 31: 523 // mach_msg_trap 524 set_argument_ptr(args[0]); 525 break; 526 case 32: 527 // mach_msg_overwrite_trap 528 set_argument_ptr(args[7]); 529 if (get_argument_ptr() == NULL) 530 set_argument_ptr(args[0]); 531 break; 532 default: 533 log->append("Unexpected mach_call_nr"); 534 return; 535 } 536 } 537} 538 539static void print_mach_msg_exit(xtrace::String* log) 540{ 541 if (get_argument_ptr() == NULL) 542 return; 543 544 const mach_msg_header_t* message = (const mach_msg_header_t*)get_argument_ptr(); 545 xtrace_start_line(log, 8); 546 print_mach_msg(log, message, message->msgh_size); 547 xtrace_start_line(log, 8); 548 xtrace_print_mig_message(log, message, get_request_port()); 549 xtrace_log("%s\n", log->c_str()); log->clear(); 550 set_argument_ptr(NULL); 551 set_request_port(MACH_PORT_NULL); 552} 553 554static void print_mach_msg_args(xtrace::String* log, int nr, void* args[]) 555{ 556 mach_msg_header_t* msg = (mach_msg_header_t*) args[0]; 557 mach_msg_option_t options = (mach_msg_option_t) (unsigned long) args[1]; 558 mach_msg_size_t send_size = (mach_msg_size_t) (unsigned long) args[2]; 559 mach_msg_size_t rcv_size = (mach_msg_size_t) (unsigned long) args[3]; 560 mach_port_name_t rcv_name = (mach_port_name_t) (unsigned long) args[4]; 561 mach_msg_timeout_t timeout = (mach_msg_timeout_t) (unsigned long) args[5]; 562 mach_port_name_t notify = (mach_port_name_t) (unsigned long) args[6]; 563 564 log->append_format("%p, ", msg); 565 566 int options_cnt = 0; 567 568#define OPTION(OPT) if (options & OPT) \ 569 { \ 570 if (options_cnt > 0) \ 571 log->append("|"); \ 572 log->append(#OPT); \ 573 options_cnt++; \ 574 } 575 576 OPTION(MACH_SEND_MSG); 577 OPTION(MACH_RCV_MSG); 578 579 OPTION(MACH_RCV_LARGE); 580 OPTION(MACH_RCV_LARGE_IDENTITY); 581 582 OPTION(MACH_SEND_TIMEOUT); 583 OPTION(MACH_SEND_INTERRUPT); 584 OPTION(MACH_SEND_NOTIFY); 585 OPTION(MACH_SEND_TRAILER); 586 OPTION(MACH_SEND_NOIMPORTANCE); 587 588 OPTION(MACH_RCV_TIMEOUT); 589 OPTION(MACH_RCV_NOTIFY); 590 OPTION(MACH_RCV_INTERRUPT); 591 OPTION(MACH_RCV_VOUCHER); 592 OPTION(MACH_RCV_OVERWRITE); 593 594#undef OPTION 595 596 if (options_cnt == 0) 597 log->append("MACH_MSG_OPTION_NONE"); 598 599 log->append_format(", %d, %d, port %d, %d, port %d", send_size, rcv_size, rcv_name, timeout, notify); 600}