1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <fcntl.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <errno.h>
25:
26: #include <mach/host_info.h>
27: #include <mach/mach.h>
28: #include <mach/mach_time.h>
29: #include <mach/message.h>
30:
31: #include <pthread.h>
32: #include <dirent.h>
33:
34: #include <sys/stat.h>
35: #include <sys/syscall.h>
36: #include <sys/sysctl.h>
37: #include <sys/types.h>
38: #include <unistd.h>
39: #include <sys/ioctl.h>
40: #include <sys/mman.h>
41: #include <sys/types.h>
42: #include <sys/dirent.h>
43: #include <sys/uio.h>
44: #include <sys/termios.h>
45: #include <sys/ptrace.h>
46: #include <net/if.h>
47:
48: #include <sys/param.h>
49: #include <sys/mount.h>
50:
51: #include <sys/attr.h>
52:
53: #include <mach/ndr.h>
54: #include <mach/mig_errors.h>
55:
56: #include <sys/xattr.h>
57:
58: #include "qemu.h"
59:
60:
61:
62: #ifdef DEBUG_SYSCALL
63: # define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
64: # define DEBUG_BEGIN_ENABLE __DEBUG_qemu_user_force_enable = 1;
65: # define DEBUG_END_ENABLE __DEBUG_qemu_user_force_enable = 0;
66:
67: # define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
68: # define DEBUG_ENABLE_ALL() static int __DEBUG_qemu_user_force_enable = 1
69: DEBUG_ENABLE_ALL();
70:
71: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
72: if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
73: } while(0)
74: #else
75: # define DEBUG_FORCE_ENABLE_LOCAL()
76: # define DEBUG_BEGIN_ENABLE
77: # define DEBUG_END_ENABLE
78:
79: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
80: #endif
81:
82: enum {
83: bswap_out = 0,
84: bswap_in = 1
85: };
86:
87: extern const char *interp_prefix;
88:
89: static inline long get_errno(long ret)
90: {
91: if (ret == -1)
92: return -errno;
93: else
94: return ret;
95: }
96:
97: static inline int is_error(long ret)
98: {
99: return (unsigned long)ret >= (unsigned long)(-4096);
100: }
101:
102:
103:
104:
105:
106: void static inline print_description_msg_header(mach_msg_header_t *hdr)
107: {
108: char *name = NULL;
109: int i;
110: struct { int number; char *name; } msg_name[] =
111: {
112:
113: { 200, "host_info" },
114: { 202, "host_page_size" },
115: { 206, "host_get_clock_service" },
116: { 206, "host_get_clock_service" },
117: { 206, "host_get_clock_service" },
118: { 306, "host_get_clock_service" },
119: { 3204, "mach_port_allocate" },
120: { 3206, "mach_port_deallocate" },
121: { 3404, "mach_ports_lookup" },
122: { 3409, "mach_task_get_special_port" },
123: { 3414, "mach_task_get_exception_ports" },
124: { 3418, "mach_semaphore_create" },
125: { 3504, "mach_semaphore_create" },
126: { 3509, "mach_semaphore_create" },
127: { 3518, "semaphore_create" },
128: { 3616, "thread_policy" },
129: { 3801, "vm_allocate" },
130: { 3802, "vm_deallocate" },
131: { 3802, "vm_deallocate" },
132: { 3803, "vm_protect" },
133: { 3812, "vm_map" },
134: { 4241776, "lu_message_send_id" },
135: { 4241876, "lu_message_reply_id" },
136: };
137:
138: for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
139: if(msg_name[i].number == hdr->msgh_id)
140: {
141: name = msg_name[i].name;
142: break;
143: }
144: }
145: if(!name)
146: DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
147: else
148: DPRINTF("%s\n", name);
149: #if 0
150: DPRINTF("Bits: %8x\n", hdr->msgh_bits);
151: DPRINTF("Size: %8x\n", hdr->msgh_size);
152: DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
153: DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
154: DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
155:
156: DPRINTF("Id : %8x\n", hdr->msgh_id);
157:
158: NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
159: DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
160: DPRINTF("%d %d %d %d %d %d %d %d\n",
161: ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
162: ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
163: #endif
164: }
165:
166: static inline void print_mach_msg_return(mach_msg_return_t ret)
167: {
168: int i, found = 0;
169: #define MACH_MSG_RET(msg) { msg, #msg }
170: struct { int code; char *name; } msg_name[] =
171: {
172:
173:
174: MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
175: MACH_MSG_RET(MACH_SEND_NO_BUFFER),
176: MACH_MSG_RET(MACH_SEND_INVALID_DATA),
177: MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
178: MACH_MSG_RET(MACH_SEND_INVALID_DEST),
179: MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
180: MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
181: MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
182: MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
183: MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
184: MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
185: MACH_MSG_RET(MACH_SEND_INTERRUPTED),
186: MACH_MSG_RET(MACH_SEND_TIMED_OUT),
187:
188: MACH_MSG_RET(MACH_RCV_BODY_ERROR),
189: MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
190:
191: MACH_MSG_RET(MACH_RCV_IN_SET),
192: MACH_MSG_RET(MACH_RCV_INTERRUPTED),
193:
194: MACH_MSG_RET(MACH_RCV_INVALID_DATA),
195: MACH_MSG_RET(MACH_RCV_INVALID_NAME),
196: MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
197: MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
198: MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
199:
200: MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
201: MACH_MSG_RET(MACH_RCV_PORT_DIED),
202:
203: MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
204: MACH_MSG_RET(MACH_RCV_TIMED_OUT),
205: MACH_MSG_RET(MACH_RCV_TOO_LARGE)
206: };
207: #undef MACH_MSG_RET
208:
209: if( ret == MACH_MSG_SUCCESS)
210: DPRINTF("MACH_MSG_SUCCESS\n");
211: else
212: {
213: for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
214: if(msg_name[i].code == ret) {
215: DPRINTF("%s\n", msg_name[i].name);
216: found = 1;
217: break;
218: }
219: }
220: if(!found)
221: qerror("unknow mach message ret code %d\n", ret);
222: }
223: }
224:
225: static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
226: {
227: hdr->msgh_bits = tswap32(hdr->msgh_bits);
228: hdr->msgh_size = tswap32(hdr->msgh_size);
229: hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
230: hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
231: hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
232: hdr->msgh_id = tswap32(hdr->msgh_id);
233: }
234:
235: struct complex_msg {
236: mach_msg_header_t hdr;
237: mach_msg_body_t body;
238: };
239:
240: static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
241: {
242: mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
243: int i,j;
244:
245: if(bswap == bswap_in)
246: tswap32s(&complex_msg->body.msgh_descriptor_count);
247:
248: DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
249:
250: for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
251: switch(descr->type)
252: {
253: case MACH_MSG_PORT_DESCRIPTOR:
254: tswap32s(&descr->name);
255: descr++;
256: break;
257: case MACH_MSG_OOL_DESCRIPTOR:
258: {
259: mach_msg_ool_descriptor_t *ool = (void *)descr;
260: tswap32s((uint32_t *)&ool->address);
261: tswap32s(&ool->size);
262:
263: descr = (mach_msg_port_descriptor_t *)(ool+1);
264: break;
265: }
266: case MACH_MSG_OOL_PORTS_DESCRIPTOR:
267: {
268: mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
269: mach_port_name_t * port_names;
270:
271: if(bswap == bswap_in)
272: {
273: tswap32s((uint32_t *)&ool_ports->address);
274: tswap32s(&ool_ports->count);
275: }
276:
277: port_names = ool_ports->address;
278:
279: for(j = 0; j < ool_ports->count; j++)
280: tswap32s(&port_names[j]);
281:
282: if(bswap == bswap_out)
283: {
284: tswap32s((uint32_t *)&ool_ports->address);
285: tswap32s(&ool_ports->count);
286: }
287:
288: descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
289: break;
290: }
291: default: qerror("unknow mach msg descriptor type %x\n", descr->type);
292: }
293: }
294: if(bswap == bswap_out)
295: tswap32s(&complex_msg->body.msgh_descriptor_count);
296: }
297:
298: static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
299: {
300: if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
301: swap_mach_msg_body((struct complex_msg *)hdr, bswap);
302:
303: swap_mach_msg_header(hdr);
304:
305: if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
306: swap_mach_msg_body((struct complex_msg *)hdr, bswap);
307: }
308:
309: static inline uint32_t target_mach_msg_trap(
310: mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
311: uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
312: {
313: extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
314: mach_msg_size_t, mach_msg_size_t, mach_port_t,
315: mach_msg_timeout_t, mach_port_t);
316: mach_msg_audit_trailer_t *trailer;
317: mach_msg_id_t msg_id;
318: uint32_t ret = 0;
319: int i;
320:
321: swap_mach_msg(hdr, bswap_in);
322:
323: msg_id = hdr->msgh_id;
324:
325: print_description_msg_header(hdr);
326:
327: ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
328:
329: print_mach_msg_return(ret);
330:
331: if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
332: {
333:
334:
335:
336:
337:
338: trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
339:
340:
341: switch(trailer->msgh_trailer_size)
342: {
343: case sizeof(mach_msg_audit_trailer_t):
344: for(i = 0; i < 8; i++)
345: tswap32s(&trailer->msgh_audit.val[i]);
346:
347: case sizeof(mach_msg_security_trailer_t):
348: tswap32s(&trailer->msgh_sender.val[0]);
349: tswap32s(&trailer->msgh_sender.val[1]);
350:
351: case sizeof(mach_msg_seqno_trailer_t):
352: tswap32s(&trailer->msgh_seqno);
353:
354: case sizeof(mach_msg_trailer_t):
355: tswap32s(&trailer->msgh_trailer_type);
356: tswap32s(&trailer->msgh_trailer_size);
357: break;
358: case 0:
359:
360: break;
361: default:
362: qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
363: break;
364: }
365: }
366:
367:
368: switch (msg_id) {
369: case 200:
370: {
371: mig_reply_error_t *err = (mig_reply_error_t *)hdr;
372: struct {
373: uint32_t unknow1;
374: uint32_t max_cpus;
375: uint32_t avail_cpus;
376: uint32_t memory_size;
377: uint32_t cpu_type;
378: uint32_t cpu_subtype;
379: } *data = (void *)(err+1);
380:
381: DPRINTF("maxcpu = 0x%x\n", data->max_cpus);
382: DPRINTF("numcpu = 0x%x\n", data->avail_cpus);
383: DPRINTF("memsize = 0x%x\n", data->memory_size);
384:
385: #if defined(TARGET_I386)
386: data->cpu_type = CPU_TYPE_I386;
387: DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
388: data->cpu_subtype = CPU_SUBTYPE_PENT;
389: DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
390: #elif defined(TARGET_PPC)
391: data->cpu_type = CPU_TYPE_POWERPC;
392: DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
393: data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
394: DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
395: #else
396: # error target not supported
397: #endif
398: break;
399: }
400: case 202:
401: {
402: mig_reply_error_t *err = (mig_reply_error_t *)hdr;
403: uint32_t *pagesize = (uint32_t *)(err+1);
404:
405: DPRINTF("pagesize = %d\n", *pagesize);
406: break;
407: }
408: default: break;
409: }
410:
411: swap_mach_msg(hdr, bswap_out);
412:
413: return ret;
414: }
415:
416: long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
417: uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
418: uint32_t arg8)
419: {
420: extern uint32_t mach_reply_port();
421:
422: long ret = 0;
423:
424: arg1 = tswap32(arg1);
425: arg2 = tswap32(arg2);
426: arg3 = tswap32(arg3);
427: arg4 = tswap32(arg4);
428: arg5 = tswap32(arg5);
429: arg6 = tswap32(arg6);
430: arg7 = tswap32(arg7);
431: arg8 = tswap32(arg8);
432:
433: DPRINTF("mach syscall %d : " , num);
434:
435: switch(num) {
436:
437: case -26:
438: DPRINTF("mach_reply_port()\n");
439: ret = mach_reply_port();
440: break;
441: case -27:
442: DPRINTF("mach_thread_self()\n");
443: ret = mach_thread_self();
444: break;
445: case -28:
446: DPRINTF("mach_task_self()\n");
447: ret = mach_task_self();
448: break;
449: case -29:
450: DPRINTF("mach_host_self()\n");
451: ret = mach_host_self();
452: break;
453: case -31:
454: DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
455: arg1, arg2, arg3, arg4, arg5, arg6, arg7);
456: ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
457: break;
458:
459: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
460: case -33:
461: DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
462: ret = semaphore_signal_trap(arg1);
463: break;
464: case -34:
465: DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
466: ret = semaphore_signal_all_trap(arg1);
467: break;
468: case -35:
469: DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
470: ret = semaphore_signal_thread_trap(arg1,arg2);
471: break;
472: #endif
473: case -36:
474: DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
475: extern int semaphore_wait_trap(int);
476: ret = semaphore_wait_trap(arg1);
477: break;
478:
479: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
480: case -37:
481: DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
482: ret = semaphore_wait_signal_trap(arg1,arg2);
483: break;
484: #endif
485: case -43:
486: DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
487: arg1, arg2, arg3, arg4, arg5);
488: ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
489: tswap32s((uint32_t*)arg3);
490: break;
491:
492: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
493: case -61:
494: DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
495: arg1, arg2, arg3);
496: ret = syscall_thread_switch(arg1, arg2, arg3);
497: break;
498: #endif
499: case -89:
500: DPRINTF("mach_timebase_info(0x%x)\n", arg1);
501: struct mach_timebase_info info;
502: ret = mach_timebase_info(&info);
503: if(!is_error(ret))
504: {
505: struct mach_timebase_info *outInfo = (void*)arg1;
506: outInfo->numer = tswap32(info.numer);
507: outInfo->denom = tswap32(info.denom);
508: }
509: break;
510: case -90:
511: DPRINTF("mach_wait_until()\n");
512: extern int mach_wait_until(uint64_t);
513: ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
514: break;
515: case -91:
516: DPRINTF("mk_timer_create()\n");
517: extern int mk_timer_create();
518: ret = mk_timer_create();
519: break;
520: case -92:
521: DPRINTF("mk_timer_destroy()\n");
522: extern int mk_timer_destroy(int);
523: ret = mk_timer_destroy(arg1);
524: break;
525: case -93:
526: DPRINTF("mk_timer_create()\n");
527: extern int mk_timer_arm(int, uint64_t);
528: