this repo has no description
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}