|
|
1.1 ! root 1: /* ! 2: * Darwin syscalls ! 3: * ! 4: * Copyright (c) 2003 Fabrice Bellard ! 5: * Copyright (c) 2006 Pierre d'Herbemont ! 6: * ! 7: * This program is free software; you can redistribute it and/or modify ! 8: * it under the terms of the GNU General Public License as published by ! 9: * the Free Software Foundation; either version 2 of the License, or ! 10: * (at your option) any later version. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, ! 13: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: * GNU General Public License for more details. ! 16: * ! 17: * You should have received a copy of the GNU General Public License ! 18: * along with this program; if not, write to the Free Software ! 19: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 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 "qemu.h" ! 57: ! 58: //#define DEBUG_SYSCALL ! 59: ! 60: #ifdef DEBUG_SYSCALL ! 61: # define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1 ! 62: # define DEBUG_BEGIN_ENABLE __DEBUG_qemu_user_force_enable = 1; ! 63: # define DEBUG_END_ENABLE __DEBUG_qemu_user_force_enable = 0; ! 64: ! 65: # define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0 ! 66: # define DEBUG_ENABLE_ALL() static int __DEBUG_qemu_user_force_enable = 1 ! 67: DEBUG_ENABLE_ALL(); ! 68: ! 69: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \ ! 70: if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \ ! 71: } while(0) ! 72: #else ! 73: # define DEBUG_FORCE_ENABLE_LOCAL() ! 74: # define DEBUG_BEGIN_ENABLE ! 75: # define DEBUG_END_ENABLE ! 76: ! 77: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0) ! 78: #endif ! 79: ! 80: enum { ! 81: bswap_out = 0, ! 82: bswap_in = 1 ! 83: }; ! 84: ! 85: extern const char *interp_prefix; ! 86: ! 87: static inline long get_errno(long ret) ! 88: { ! 89: if (ret == -1) ! 90: return -errno; ! 91: else ! 92: return ret; ! 93: } ! 94: ! 95: static inline int is_error(long ret) ! 96: { ! 97: return (unsigned long)ret >= (unsigned long)(-4096); ! 98: } ! 99: ! 100: /* ------------------------------------------------------------ ! 101: Mach syscall handling ! 102: */ ! 103: ! 104: void static inline print_description_msg_header(mach_msg_header_t *hdr) ! 105: { ! 106: char *name = NULL; ! 107: int i; ! 108: struct { int number; char *name; } msg_name[] = ! 109: { ! 110: /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */ ! 111: { 200, "host_info" }, ! 112: { 202, "host_page_size" }, ! 113: { 206, "host_get_clock_service" }, ! 114: { 206, "host_get_clock_service" }, ! 115: { 206, "host_get_clock_service" }, ! 116: { 306, "host_get_clock_service" }, ! 117: { 3204, "mach_port_allocate" }, ! 118: { 3206, "mach_port_deallocate" }, ! 119: { 3404, "mach_ports_lookup" }, ! 120: { 3409, "mach_task_get_special_port" }, ! 121: { 3414, "mach_task_get_exception_ports" }, ! 122: { 3418, "mach_semaphore_create" }, ! 123: { 3504, "mach_semaphore_create" }, ! 124: { 3509, "mach_semaphore_create" }, ! 125: { 3518, "semaphore_create" }, ! 126: { 3616, "thread_policy" }, ! 127: { 3801, "vm_allocate" }, ! 128: { 3802, "vm_deallocate" }, ! 129: { 3802, "vm_deallocate" }, ! 130: { 3803, "vm_protect" }, ! 131: { 3812, "vm_map" }, ! 132: { 4241776, "lu_message_send_id" }, /* lookupd */ ! 133: { 4241876, "lu_message_reply_id" }, /* lookupd */ ! 134: }; ! 135: ! 136: for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) { ! 137: if(msg_name[i].number == hdr->msgh_id) ! 138: { ! 139: name = msg_name[i].name; ! 140: break; ! 141: } ! 142: } ! 143: if(!name) ! 144: DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id); ! 145: else ! 146: DPRINTF("%s\n", name); ! 147: #if 0 ! 148: DPRINTF("Bits: %8x\n", hdr->msgh_bits); ! 149: DPRINTF("Size: %8x\n", hdr->msgh_size); ! 150: DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port); ! 151: DPRINTF("Locl: %8x\n", hdr->msgh_local_port); ! 152: DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved); ! 153: ! 154: DPRINTF("Id : %8x\n", hdr->msgh_id); ! 155: ! 156: NDR_record_t *ndr = (NDR_record_t *)(hdr + 1); ! 157: DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr); ! 158: DPRINTF("%d %d %d %d %d %d %d %d\n", ! 159: ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding, ! 160: ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2); ! 161: #endif ! 162: } ! 163: ! 164: static inline void print_mach_msg_return(mach_msg_return_t ret) ! 165: { ! 166: int i, found = 0; ! 167: #define MACH_MSG_RET(msg) { msg, #msg } ! 168: struct { int code; char *name; } msg_name[] = ! 169: { ! 170: /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */ ! 171: /* send message */ ! 172: MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL), ! 173: MACH_MSG_RET(MACH_SEND_NO_BUFFER), ! 174: MACH_MSG_RET(MACH_SEND_INVALID_DATA), ! 175: MACH_MSG_RET(MACH_SEND_INVALID_HEADER), ! 176: MACH_MSG_RET(MACH_SEND_INVALID_DEST), ! 177: MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY), ! 178: MACH_MSG_RET(MACH_SEND_INVALID_REPLY), ! 179: MACH_MSG_RET(MACH_SEND_INVALID_TRAILER), ! 180: MACH_MSG_RET(MACH_SEND_INVALID_MEMORY), ! 181: MACH_MSG_RET(MACH_SEND_INVALID_RIGHT), ! 182: MACH_MSG_RET(MACH_SEND_INVALID_TYPE), ! 183: MACH_MSG_RET(MACH_SEND_INTERRUPTED), ! 184: MACH_MSG_RET(MACH_SEND_TIMED_OUT), ! 185: ! 186: MACH_MSG_RET(MACH_RCV_BODY_ERROR), ! 187: MACH_MSG_RET(MACH_RCV_HEADER_ERROR), ! 188: ! 189: MACH_MSG_RET(MACH_RCV_IN_SET), ! 190: MACH_MSG_RET(MACH_RCV_INTERRUPTED), ! 191: ! 192: MACH_MSG_RET(MACH_RCV_INVALID_DATA), ! 193: MACH_MSG_RET(MACH_RCV_INVALID_NAME), ! 194: MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY), ! 195: MACH_MSG_RET(MACH_RCV_INVALID_TRAILER), ! 196: MACH_MSG_RET(MACH_RCV_INVALID_TYPE), ! 197: ! 198: MACH_MSG_RET(MACH_RCV_PORT_CHANGED), ! 199: MACH_MSG_RET(MACH_RCV_PORT_DIED), ! 200: ! 201: MACH_MSG_RET(MACH_RCV_SCATTER_SMALL), ! 202: MACH_MSG_RET(MACH_RCV_TIMED_OUT), ! 203: MACH_MSG_RET(MACH_RCV_TOO_LARGE) ! 204: }; ! 205: #undef MACH_MSG_RET ! 206: ! 207: if( ret == MACH_MSG_SUCCESS) ! 208: DPRINTF("MACH_MSG_SUCCESS\n"); ! 209: else ! 210: { ! 211: for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) { ! 212: if(msg_name[i].code == ret) { ! 213: DPRINTF("%s\n", msg_name[i].name); ! 214: found = 1; ! 215: break; ! 216: } ! 217: } ! 218: if(!found) ! 219: qerror("unknow mach message ret code %d\n", ret); ! 220: } ! 221: } ! 222: ! 223: static inline void swap_mach_msg_header(mach_msg_header_t *hdr) ! 224: { ! 225: hdr->msgh_bits = tswap32(hdr->msgh_bits); ! 226: hdr->msgh_size = tswap32(hdr->msgh_size); ! 227: hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port); ! 228: hdr->msgh_local_port = tswap32(hdr->msgh_local_port); ! 229: hdr->msgh_reserved = tswap32(hdr->msgh_reserved); ! 230: hdr->msgh_id = tswap32(hdr->msgh_id); ! 231: } ! 232: ! 233: struct complex_msg { ! 234: mach_msg_header_t hdr; ! 235: mach_msg_body_t body; ! 236: }; ! 237: ! 238: static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap) ! 239: { ! 240: mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1); ! 241: int i,j; ! 242: ! 243: if(bswap == bswap_in) ! 244: tswap32s(&complex_msg->body.msgh_descriptor_count); ! 245: ! 246: DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count); ! 247: ! 248: for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) { ! 249: switch(descr->type) ! 250: { ! 251: case MACH_MSG_PORT_DESCRIPTOR: ! 252: tswap32s(&descr->name); ! 253: descr++; ! 254: break; ! 255: case MACH_MSG_OOL_DESCRIPTOR: ! 256: { ! 257: mach_msg_ool_descriptor_t *ool = (void *)descr; ! 258: tswap32s((uint32_t *)&ool->address); ! 259: tswap32s(&ool->size); ! 260: ! 261: descr = (mach_msg_port_descriptor_t *)(ool+1); ! 262: break; ! 263: } ! 264: case MACH_MSG_OOL_PORTS_DESCRIPTOR: ! 265: { ! 266: mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr; ! 267: mach_port_name_t * port_names; ! 268: ! 269: if(bswap == bswap_in) ! 270: { ! 271: tswap32s((uint32_t *)&ool_ports->address); ! 272: tswap32s(&ool_ports->count); ! 273: } ! 274: ! 275: port_names = ool_ports->address; ! 276: ! 277: for(j = 0; j < ool_ports->count; j++) ! 278: tswap32s(&port_names[j]); ! 279: ! 280: if(bswap == bswap_out) ! 281: { ! 282: tswap32s((uint32_t *)&ool_ports->address); ! 283: tswap32s(&ool_ports->count); ! 284: } ! 285: ! 286: descr = (mach_msg_port_descriptor_t *)(ool_ports+1); ! 287: break; ! 288: } ! 289: default: qerror("unknow mach msg descriptor type %x\n", descr->type); ! 290: } ! 291: } ! 292: if(bswap == bswap_out) ! 293: tswap32s(&complex_msg->body.msgh_descriptor_count); ! 294: } ! 295: ! 296: static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap) ! 297: { ! 298: if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX) ! 299: swap_mach_msg_body((struct complex_msg *)hdr, bswap); ! 300: ! 301: swap_mach_msg_header(hdr); ! 302: ! 303: if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX) ! 304: swap_mach_msg_body((struct complex_msg *)hdr, bswap); ! 305: } ! 306: ! 307: static inline uint32_t target_mach_msg_trap( ! 308: mach_msg_header_t *hdr, uint32_t options, uint32_t send_size, ! 309: uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify) ! 310: { ! 311: extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, ! 312: mach_msg_size_t, mach_msg_size_t, mach_port_t, ! 313: mach_msg_timeout_t, mach_port_t); ! 314: mach_msg_audit_trailer_t *trailer; ! 315: mach_msg_id_t msg_id; ! 316: uint32_t ret = 0; ! 317: int i; ! 318: ! 319: swap_mach_msg(hdr, bswap_in); ! 320: ! 321: msg_id = hdr->msgh_id; ! 322: ! 323: print_description_msg_header(hdr); ! 324: ! 325: ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify); ! 326: ! 327: print_mach_msg_return(ret); ! 328: ! 329: if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) ) ! 330: { ! 331: /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should ! 332: probably always bswap it */ ! 333: /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in ! 334: natural_t units but according to xnu/osfmk/mach/message.h: "The size of ! 335: the message must be specified in bytes" */ ! 336: trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size); ! 337: /* XXX: Should probably do that based on the option asked by the sender, but dealing ! 338: with kernel answer seems more sound */ ! 339: switch(trailer->msgh_trailer_size) ! 340: { ! 341: case sizeof(mach_msg_audit_trailer_t): ! 342: for(i = 0; i < 8; i++) ! 343: tswap32s(&trailer->msgh_audit.val[i]); ! 344: /* Fall in mach_msg_security_trailer_t case */ ! 345: case sizeof(mach_msg_security_trailer_t): ! 346: tswap32s(&trailer->msgh_sender.val[0]); ! 347: tswap32s(&trailer->msgh_sender.val[1]); ! 348: /* Fall in mach_msg_seqno_trailer_t case */ ! 349: case sizeof(mach_msg_seqno_trailer_t): ! 350: tswap32s(&trailer->msgh_seqno); ! 351: /* Fall in mach_msg_trailer_t case */ ! 352: case sizeof(mach_msg_trailer_t): ! 353: tswap32s(&trailer->msgh_trailer_type); ! 354: tswap32s(&trailer->msgh_trailer_size); ! 355: break; ! 356: case 0: ! 357: /* Safer not to byteswap, but probably wrong */ ! 358: break; ! 359: default: ! 360: qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size); ! 361: break; ! 362: } ! 363: } ! 364: ! 365: /* Special message handling */ ! 366: switch (msg_id) { ! 367: case 200: /* host_info */ ! 368: { ! 369: mig_reply_error_t *err = (mig_reply_error_t *)hdr; ! 370: struct host_basic_info *data = (void *)(err+1); ! 371: ! 372: DPRINTF("maxcpu = 0x%x\n", data->max_cpus); ! 373: DPRINTF("numcpu = 0x%x\n", data->avail_cpus); ! 374: DPRINTF("memsize = 0x%x\n", data->memory_size); ! 375: ! 376: #if defined(TARGET_I386) ! 377: data->cpu_type = CPU_TYPE_I386; ! 378: DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type); ! 379: data->cpu_subtype = CPU_SUBTYPE_PENT; ! 380: DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype); ! 381: #elif defined(TARGET_PPC) ! 382: data->cpu_type = CPU_TYPE_POWERPC; ! 383: DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type); ! 384: data->cpu_subtype = CPU_SUBTYPE_POWERPC_750; ! 385: DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype); ! 386: #else ! 387: # error target not supported ! 388: #endif ! 389: break; ! 390: } ! 391: case 202: /* host_page_size */ ! 392: { ! 393: mig_reply_error_t *err = (mig_reply_error_t *)hdr; ! 394: uint32_t *pagesize = (uint32_t *)(err+1); ! 395: ! 396: DPRINTF("pagesize = %d\n", *pagesize); ! 397: break; ! 398: } ! 399: default: break; ! 400: } ! 401: ! 402: swap_mach_msg(hdr, bswap_out); ! 403: ! 404: return ret; ! 405: } ! 406: ! 407: long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, ! 408: uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, ! 409: uint32_t arg8) ! 410: { ! 411: extern uint32_t mach_reply_port(); ! 412: ! 413: long ret = 0; ! 414: ! 415: arg1 = tswap32(arg1); ! 416: arg2 = tswap32(arg2); ! 417: arg3 = tswap32(arg3); ! 418: arg4 = tswap32(arg4); ! 419: arg5 = tswap32(arg5); ! 420: arg6 = tswap32(arg6); ! 421: arg7 = tswap32(arg7); ! 422: arg8 = tswap32(arg8); ! 423: ! 424: DPRINTF("mach syscall %d : " , num); ! 425: ! 426: switch(num) { ! 427: /* see xnu/osfmk/mach/syscall_sw.h */ ! 428: case -26: ! 429: DPRINTF("mach_reply_port()\n"); ! 430: ret = mach_reply_port(); ! 431: break; ! 432: case -27: ! 433: DPRINTF("mach_thread_self()\n"); ! 434: ret = mach_thread_self(); ! 435: break; ! 436: case -28: ! 437: DPRINTF("mach_task_self()\n"); ! 438: ret = mach_task_self(); ! 439: break; ! 440: case -29: ! 441: DPRINTF("mach_host_self()\n"); ! 442: ret = mach_host_self(); ! 443: break; ! 444: case -31: ! 445: DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", ! 446: arg1, arg2, arg3, arg4, arg5, arg6, arg7); ! 447: ! 448: ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7); ! 449: ! 450: break; ! 451: case -36: ! 452: DPRINTF("semaphore_wait_trap(0x%x)\n", arg1); ! 453: extern int semaphore_wait_trap(int); // XXX: is there any header for that? ! 454: ret = semaphore_wait_trap(arg1); ! 455: break; ! 456: case -43: ! 457: DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", ! 458: arg1, arg2, arg3, arg4, arg5); ! 459: ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5); ! 460: tswap32s((uint32_t*)arg3); ! 461: break; ! 462: case -89: ! 463: DPRINTF("mach_timebase_info(0x%x)\n", arg1); ! 464: struct mach_timebase_info info; ! 465: ret = mach_timebase_info(&info); ! 466: if(!is_error(ret)) ! 467: { ! 468: struct mach_timebase_info *outInfo = (void*)arg1; ! 469: outInfo->numer = tswap32(info.numer); ! 470: outInfo->denom = tswap32(info.denom); ! 471: } ! 472: break; ! 473: case -90: ! 474: DPRINTF("mach_wait_until()\n"); ! 475: extern int mach_wait_until(uint64_t); // XXX: is there any header for that? ! 476: ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1); ! 477: break; ! 478: case -91: ! 479: DPRINTF("mk_timer_create()\n"); ! 480: extern int mk_timer_create(); // XXX: is there any header for that? ! 481: ret = mk_timer_create(); ! 482: break; ! 483: case -92: ! 484: DPRINTF("mk_timer_destroy()\n"); ! 485: extern int mk_timer_destroy(int); // XXX: is there any header for that? ! 486: ret = mk_timer_destroy(arg1); ! 487: break; ! 488: case -93: ! 489: DPRINTF("mk_timer_create()\n"); ! 490: extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that? ! 491: ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2); ! 492: break; ! 493: case -94: ! 494: DPRINTF("mk_timer_cancel()\n"); ! 495: extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that? ! 496: ret = mk_timer_cancel(arg1, (uint64_t *)arg2); ! 497: if((!is_error(ret)) && arg2) ! 498: tswap64s((uint64_t *)arg2); ! 499: break; ! 500: default: ! 501: gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num); ! 502: gdb_handlesig (cpu_env, SIGTRAP); ! 503: exit(0); ! 504: break; ! 505: } ! 506: return ret; ! 507: } ! 508: ! 509: /* ------------------------------------------------------------ ! 510: thread type syscall handling ! 511: */ ! 512: long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, ! 513: uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, ! 514: uint32_t arg8) ! 515: { ! 516: extern uint32_t cthread_set_self(uint32_t); ! 517: extern uint32_t processor_facilities_used(); ! 518: long ret = 0; ! 519: ! 520: arg1 = tswap32(arg1); ! 521: arg2 = tswap32(arg2); ! 522: arg3 = tswap32(arg3); ! 523: arg4 = tswap32(arg4); ! 524: arg5 = tswap32(arg5); ! 525: arg6 = tswap32(arg6); ! 526: arg7 = tswap32(arg7); ! 527: arg8 = tswap32(arg8); ! 528: ! 529: DPRINTF("thread syscall %d : " , num); ! 530: ! 531: switch(num) { ! 532: #ifdef TARGET_I386 ! 533: case 0x3: ! 534: #endif ! 535: case 0x7FF1: /* cthread_set_self */ ! 536: DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1); ! 537: ret = cthread_set_self(arg1); ! 538: #ifdef TARGET_I386 ! 539: /* we need to update the LDT with the address of the thread */ ! 540: write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1, ! 541: DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | ! 542: (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); ! 543: /* New i386 convention, %gs should be set to our this LDT entry */ ! 544: cpu_x86_load_seg(cpu_env, R_GS, 0x27); ! 545: /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/ ! 546: ret = 0x27; ! 547: #endif ! 548: break; ! 549: case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */ ! 550: DPRINTF("pthread_self()\n"); ! 551: ret = (uint32_t)pthread_self(); ! 552: break; ! 553: case 0x7FF3: ! 554: DPRINTF("processor_facilities_used()\n"); ! 555: #ifdef __i386__ ! 556: qerror("processor_facilities_used: not implemented!\n"); ! 557: #else ! 558: ret = (uint32_t)processor_facilities_used(); ! 559: #endif ! 560: break; ! 561: default: ! 562: gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num); ! 563: gdb_handlesig (cpu_env, SIGTRAP); ! 564: exit(0); ! 565: break; ! 566: } ! 567: return ret; ! 568: } ! 569: ! 570: /* ------------------------------------------------------------ ! 571: ioctl handling ! 572: */ ! 573: static inline void byteswap_termios(struct termios *t) ! 574: { ! 575: tswap32s((uint32_t*)&t->c_iflag); ! 576: tswap32s((uint32_t*)&t->c_oflag); ! 577: tswap32s((uint32_t*)&t->c_cflag); ! 578: tswap32s((uint32_t*)&t->c_lflag); ! 579: /* 20 (char) bytes then */ ! 580: tswap32s((uint32_t*)&t->c_ispeed); ! 581: tswap32s((uint32_t*)&t->c_ospeed); ! 582: } ! 583: ! 584: static inline void byteswap_winsize(struct winsize *w) ! 585: { ! 586: tswap16s(&w->ws_row); ! 587: tswap16s(&w->ws_col); ! 588: tswap16s(&w->ws_xpixel); ! 589: tswap16s(&w->ws_ypixel); ! 590: } ! 591: ! 592: #define STRUCT(name, list...) STRUCT_ ## name, ! 593: #define STRUCT_SPECIAL(name) STRUCT_ ## name, ! 594: enum { ! 595: #include "ioctls_types.h" ! 596: }; ! 597: #undef STRUCT ! 598: #undef STRUCT_SPECIAL ! 599: ! 600: #define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL }; ! 601: #define STRUCT_SPECIAL(name) ! 602: #include "ioctls_types.h" ! 603: #undef STRUCT ! 604: #undef STRUCT_SPECIAL ! 605: ! 606: typedef struct IOCTLEntry { ! 607: unsigned int target_cmd; ! 608: unsigned int host_cmd; ! 609: const char *name; ! 610: int access; ! 611: const argtype arg_type[5]; ! 612: } IOCTLEntry; ! 613: ! 614: #define IOC_R 0x0001 ! 615: #define IOC_W 0x0002 ! 616: #define IOC_RW (IOC_R | IOC_W) ! 617: ! 618: #define MAX_STRUCT_SIZE 4096 ! 619: ! 620: IOCTLEntry ioctl_entries[] = { ! 621: #define IOCTL(cmd, access, types...) \ ! 622: { cmd, cmd, #cmd, access, { types } }, ! 623: #include "ioctls.h" ! 624: { 0, 0, }, ! 625: }; ! 626: ! 627: /* ??? Implement proper locking for ioctls. */ ! 628: static long do_ioctl(long fd, long cmd, long arg) ! 629: { ! 630: const IOCTLEntry *ie; ! 631: const argtype *arg_type; ! 632: int ret; ! 633: uint8_t buf_temp[MAX_STRUCT_SIZE]; ! 634: int target_size; ! 635: void *argptr; ! 636: ! 637: ie = ioctl_entries; ! 638: for(;;) { ! 639: if (ie->target_cmd == 0) { ! 640: gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd); ! 641: return -ENOSYS; ! 642: } ! 643: if (ie->target_cmd == cmd) ! 644: break; ! 645: ie++; ! 646: } ! 647: arg_type = ie->arg_type; ! 648: #if defined(DEBUG) ! 649: gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name); ! 650: #endif ! 651: switch(arg_type[0]) { ! 652: case TYPE_NULL: ! 653: /* no argument */ ! 654: ret = get_errno(ioctl(fd, ie->host_cmd)); ! 655: break; ! 656: case TYPE_PTRVOID: ! 657: case TYPE_INT: ! 658: /* int argment */ ! 659: ret = get_errno(ioctl(fd, ie->host_cmd, arg)); ! 660: break; ! 661: case TYPE_PTR: ! 662: arg_type++; ! 663: target_size = thunk_type_size(arg_type, 0); ! 664: switch(ie->access) { ! 665: case IOC_R: ! 666: ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); ! 667: if (!is_error(ret)) { ! 668: argptr = lock_user(arg, target_size, 0); ! 669: thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); ! 670: unlock_user(argptr, arg, target_size); ! 671: } ! 672: break; ! 673: case IOC_W: ! 674: argptr = lock_user(arg, target_size, 1); ! 675: thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); ! 676: unlock_user(argptr, arg, 0); ! 677: ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); ! 678: break; ! 679: default: ! 680: case IOC_RW: ! 681: argptr = lock_user(arg, target_size, 1); ! 682: thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); ! 683: unlock_user(argptr, arg, 0); ! 684: ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); ! 685: if (!is_error(ret)) { ! 686: argptr = lock_user(arg, target_size, 0); ! 687: thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); ! 688: unlock_user(argptr, arg, target_size); ! 689: } ! 690: break; ! 691: } ! 692: break; ! 693: default: ! 694: gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]); ! 695: ret = -ENOSYS; ! 696: break; ! 697: } ! 698: return ret; ! 699: } ! 700: ! 701: /* ------------------------------------------------------------ ! 702: Unix syscall handling ! 703: */ ! 704: ! 705: static inline void byteswap_attrlist(struct attrlist *a) ! 706: { ! 707: tswap16s(&a->bitmapcount); ! 708: tswap16s(&a->reserved); ! 709: tswap32s(&a->commonattr); ! 710: tswap32s(&a->volattr); ! 711: tswap32s(&a->dirattr); ! 712: tswap32s(&a->fileattr); ! 713: tswap32s(&a->forkattr); ! 714: } ! 715: ! 716: struct attrbuf_header { ! 717: unsigned long length; ! 718: }; ! 719: ! 720: static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist) ! 721: { ! 722: DPRINTF("attrBuf.lenght %lx\n", attrbuf->length); ! 723: } ! 724: ! 725: static inline void byteswap_statfs(struct statfs *s) ! 726: { ! 727: tswap16s((uint16_t*)&s->f_otype); ! 728: tswap16s((uint16_t*)&s->f_oflags); ! 729: tswap32s((uint32_t*)&s->f_bsize); ! 730: tswap32s((uint32_t*)&s->f_iosize); ! 731: tswap32s((uint32_t*)&s->f_blocks); ! 732: tswap32s((uint32_t*)&s->f_bfree); ! 733: tswap32s((uint32_t*)&s->f_bavail); ! 734: tswap32s((uint32_t*)&s->f_files); ! 735: tswap32s((uint32_t*)&s->f_ffree); ! 736: tswap32s((uint32_t*)&s->f_fsid.val[0]); ! 737: tswap32s((uint32_t*)&s->f_fsid.val[1]); ! 738: tswap16s((uint16_t*)&s->f_reserved1); ! 739: tswap16s((uint16_t*)&s->f_type); ! 740: tswap32s((uint32_t*)&s->f_flags); ! 741: } ! 742: ! 743: static inline void byteswap_stat(struct stat *s) ! 744: { ! 745: tswap32s((uint32_t*)&s->st_dev); ! 746: tswap32s(&s->st_ino); ! 747: tswap16s(&s->st_mode); ! 748: tswap16s(&s->st_nlink); ! 749: tswap32s(&s->st_uid); ! 750: tswap32s(&s->st_gid); ! 751: tswap32s((uint32_t*)&s->st_rdev); ! 752: tswap32s((uint32_t*)&s->st_atimespec.tv_sec); ! 753: tswap32s((uint32_t*)&s->st_atimespec.tv_nsec); ! 754: tswap32s((uint32_t*)&s->st_mtimespec.tv_sec); ! 755: tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec); ! 756: tswap32s((uint32_t*)&s->st_ctimespec.tv_sec); ! 757: tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec); ! 758: tswap64s((uint64_t*)&s->st_size); ! 759: tswap64s((uint64_t*)&s->st_blocks); ! 760: tswap32s((uint32_t*)&s->st_blksize); ! 761: tswap32s(&s->st_flags); ! 762: tswap32s(&s->st_gen); ! 763: } ! 764: ! 765: static inline void byteswap_dirents(struct dirent *d, int bytes) ! 766: { ! 767: char *b; ! 768: for( b = (char*)d; (int)b < (int)d+bytes; ) ! 769: { ! 770: unsigned short s = ((struct dirent *)b)->d_reclen; ! 771: tswap32s(&((struct dirent *)b)->d_ino); ! 772: tswap16s(&((struct dirent *)b)->d_reclen); ! 773: if(s<=0) ! 774: break; ! 775: b += s; ! 776: } ! 777: } ! 778: ! 779: static inline void byteswap_iovec(struct iovec *v, int n) ! 780: { ! 781: int i; ! 782: for(i = 0; i < n; i++) ! 783: { ! 784: tswap32s((uint32_t*)&v[i].iov_base); ! 785: tswap32s((uint32_t*)&v[i].iov_len); ! 786: } ! 787: } ! 788: ! 789: static inline void byteswap_timeval(struct timeval *t) ! 790: { ! 791: tswap32s((uint32_t*)&t->tv_sec); ! 792: tswap32s((uint32_t*)&t->tv_usec); ! 793: } ! 794: ! 795: long do_unix_syscall_indirect(void *cpu_env, int num); ! 796: long do_sync(); ! 797: long do_exit(uint32_t arg1); ! 798: long do_getlogin(char *out, uint32_t size); ! 799: long do_open(char * arg1, uint32_t arg2, uint32_t arg3); ! 800: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3); ! 801: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3); ! 802: long do_execve(char* arg1, char ** arg2, char ** arg3); ! 803: long do_getgroups(uint32_t arg1, gid_t * arg2); ! 804: long do_gettimeofday(struct timeval * arg1, void * arg2); ! 805: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3); ! 806: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3); ! 807: long do_utimes(char * arg1, struct timeval * arg2); ! 808: long do_futimes(uint32_t arg1, struct timeval * arg2); ! 809: long do_statfs(char * arg1, struct statfs * arg2); ! 810: long do_fstatfs(uint32_t arg1, struct statfs * arg2); ! 811: long do_stat(char * arg1, struct stat * arg2); ! 812: long do_fstat(uint32_t arg1, struct stat * arg2); ! 813: long do_lstat(char * arg1, struct stat * arg2); ! 814: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4); ! 815: long do_lseek(void *cpu_env, int num); ! 816: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */); ! 817: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5); ! 818: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8); ! 819: long do_fcntl(int fd, int cmd, int arg); ! 820: ! 821: long no_syscall(void *cpu_env, int num); ! 822: ! 823: long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4) ! 824: { ! 825: DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4); ! 826: long ret = pread(arg1, arg2, arg3, arg4); ! 827: return ret; ! 828: } ! 829: ! 830: long do_read(int d, void *buf, size_t nbytes) ! 831: { ! 832: DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes); ! 833: long ret = get_errno(read(d, buf, nbytes)); ! 834: if(!is_error(ret)) ! 835: DPRINTF("%x\n", *(uint32_t*)buf); ! 836: return ret; ! 837: } ! 838: ! 839: long unimpl_unix_syscall(void *cpu_env, int num); ! 840: ! 841: typedef long (*syscall_function_t)(void *cpu_env, int num); ! 842: ! 843: ! 844: /* define a table that will handle the syscall number->function association */ ! 845: #define VOID void ! 846: #define INT (uint32_t)get_int_arg(&i, cpu_env) ! 847: #define INT64 (uint64_t)get_int64_arg(&i, cpu_env) ! 848: #define UINT (unsigned int)INT ! 849: #define PTR (void*)INT ! 850: ! 851: #define SIZE INT ! 852: #define OFFSET INT64 ! 853: ! 854: #define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) { return (long)function(); } ! 855: #define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; return (long)function(arg1); } ! 856: #define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); } ! 857: #define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); } ! 858: #define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); } ! 859: #define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; return (long)function(arg1, arg2, arg3, arg4, arg5); } ! 860: #define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); } ! 861: #define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } ! 862: #define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } ! 863: #define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args) ! 864: #define WRAPPER_CALL_NOERRNO(function, nargs, args...) WRAPPER_CALL_DIRECT(function, nargs, args) ! 865: #define WRAPPER_CALL_INDIRECT(function, nargs, args...) ! 866: #define ENTRY(name, number, function, nargs, call_type, args...) WRAPPER_##call_type(function, nargs, args) ! 867: ! 868: #include "syscalls.h" ! 869: ! 870: #undef ENTRY ! 871: #undef WRAPPER_CALL_DIRECT ! 872: #undef WRAPPER_CALL_NOERRNO ! 873: #undef WRAPPER_CALL_INDIRECT ! 874: #undef OFFSET ! 875: #undef SIZE ! 876: #undef INT ! 877: #undef PTR ! 878: #undef INT64 ! 879: ! 880: #define _ENTRY(name, number, function, nargs, call_type) [number] = {\ ! 881: name, \ ! 882: number, \ ! 883: (syscall_function_t)function, \ ! 884: nargs, \ ! 885: call_type \ ! 886: }, ! 887: ! 888: #define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, __qemu_##function, nargs, call_type) ! 889: #define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) ! 890: #define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type) ! 891: #define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type) ! 892: ! 893: #define CALL_DIRECT 1 ! 894: #define CALL_INDIRECT 2 ! 895: #define CALL_NOERRNO (CALL_DIRECT | 4 /* = 5 */) ! 896: ! 897: struct unix_syscall { ! 898: char * name; ! 899: int number; ! 900: syscall_function_t function; ! 901: int nargs; ! 902: int call_type; ! 903: } unix_syscall_table[SYS_MAXSYSCALL] = { ! 904: #include "syscalls.h" ! 905: }; ! 906: ! 907: #undef ENTRY ! 908: #undef _ENTRY ! 909: #undef ENTRY_CALL_DIRECT ! 910: #undef ENTRY_CALL_INDIRECT ! 911: #undef ENTRY_CALL_NOERRNO ! 912: ! 913: /* Actual syscalls implementation */ ! 914: ! 915: long do_unix_syscall_indirect(void *cpu_env, int num) ! 916: { ! 917: long ret; ! 918: int new_num; ! 919: int i = 0; ! 920: ! 921: new_num = get_int_arg(&i, cpu_env); ! 922: #ifdef TARGET_I386 ! 923: ((CPUX86State*)cpu_env)->regs[R_ESP] += 4; ! 924: /* XXX: not necessary */ ! 925: ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num; ! 926: #elif TARGET_PPC ! 927: { ! 928: int i; ! 929: uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr; ! 930: for(i = 3; i < 11; i++) ! 931: *regs[i] = *regs[i+1]; ! 932: /* XXX: not necessary */ ! 933: *regs[0] = new_num; ! 934: } ! 935: #endif ! 936: ret = do_unix_syscall(cpu_env, new_num); ! 937: #ifdef TARGET_I386 ! 938: ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4; ! 939: /* XXX: not necessary */ ! 940: ((CPUX86State*)cpu_env)->regs[R_EAX] = num; ! 941: #elif TARGET_PPC ! 942: { ! 943: int i; ! 944: /* XXX: not really needed those regs are volatile accross calls */ ! 945: uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr; ! 946: for(i = 11; i > 3; i--) ! 947: *regs[i] = *regs[i-1]; ! 948: regs[3] = new_num; ! 949: *regs[0] = num; ! 950: } ! 951: #endif ! 952: return ret; ! 953: } ! 954: ! 955: long do_exit(uint32_t arg1) ! 956: { ! 957: exit(arg1); ! 958: /* not reached */ ! 959: return -1; ! 960: } ! 961: ! 962: long do_sync() ! 963: { ! 964: sync(); ! 965: return 0; ! 966: } ! 967: ! 968: long do_getlogin(char *out, uint32_t size) ! 969: { ! 970: char *login = getlogin(); ! 971: if(!login) ! 972: return -1; ! 973: memcpy(out, login, size); ! 974: return 0; ! 975: } ! 976: long do_open(char * arg1, uint32_t arg2, uint32_t arg3) ! 977: { ! 978: /* XXX: don't let the %s stay in there */ ! 979: DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3); ! 980: return get_errno(open(arg1, arg2, arg3)); ! 981: } ! 982: ! 983: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3) ! 984: { ! 985: long ret; ! 986: DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3); ! 987: ret = get_errno(getfsstat(arg1, arg2, arg3)); ! 988: if((!is_error(ret)) && arg1) ! 989: byteswap_statfs(arg1); ! 990: return ret; ! 991: } ! 992: ! 993: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3) ! 994: { ! 995: long ret; ! 996: DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3); ! 997: gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3); ! 998: if(arg2) ! 999: tswap32s(arg2); ! 1000: ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3)); ! 1001: if((!is_error(ret)) && arg3) ! 1002: tswap32s(arg3); ! 1003: if(arg2) ! 1004: tswap32s(arg2); ! 1005: return ret; ! 1006: } ! 1007: ! 1008: long do_execve(char* arg1, char ** arg2, char ** arg3) ! 1009: { ! 1010: long ret; ! 1011: char **argv = arg2; ! 1012: char **envp = arg3; ! 1013: int argc; ! 1014: int envc; ! 1015: ! 1016: /* XXX: don't let the %s stay in here */ ! 1017: DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3); ! 1018: ! 1019: for(argc = 0; argv[argc]; argc++); ! 1020: for(envc = 0; envp[envc]; envc++); ! 1021: ! 1022: argv = (char**)malloc(sizeof(char*)*argc); ! 1023: envp = (char**)malloc(sizeof(char*)*envc); ! 1024: ! 1025: for(; argc >= 0; argc--) ! 1026: argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]); ! 1027: ! 1028: for(; envc >= 0; envc--) ! 1029: envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]); ! 1030: ! 1031: ret = get_errno(execve(arg1, argv, envp)); ! 1032: free(argv); ! 1033: free(envp); ! 1034: return ret; ! 1035: } ! 1036: ! 1037: long do_getgroups(uint32_t arg1, gid_t * arg2) ! 1038: { ! 1039: long ret; ! 1040: int i; ! 1041: DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2); ! 1042: ret = get_errno(getgroups(arg1, arg2)); ! 1043: if(ret > 0) ! 1044: for(i = 0; i < arg1; i++) ! 1045: tswap32s(&arg2[i]); ! 1046: return ret; ! 1047: } ! 1048: ! 1049: long do_gettimeofday(struct timeval * arg1, void * arg2) ! 1050: { ! 1051: long ret; ! 1052: DPRINTF("gettimeofday(%p, %p)\n", ! 1053: arg1, arg2); ! 1054: ret = get_errno(gettimeofday(arg1, arg2)); ! 1055: if(!is_error(ret)) ! 1056: { ! 1057: /* timezone no longer used according to the manpage, so don't bother with it */ ! 1058: byteswap_timeval(arg1); ! 1059: } ! 1060: return ret; ! 1061: } ! 1062: ! 1063: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3) ! 1064: { ! 1065: long ret; ! 1066: DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3); ! 1067: if(arg2) ! 1068: byteswap_iovec(arg2, arg3); ! 1069: ret = get_errno(readv(arg1, arg2, arg3)); ! 1070: if((!is_error(ret)) && arg2) ! 1071: byteswap_iovec(arg2, arg3); ! 1072: return ret; ! 1073: } ! 1074: ! 1075: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3) ! 1076: { ! 1077: long ret; ! 1078: DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3); ! 1079: if(arg2) ! 1080: byteswap_iovec(arg2, arg3); ! 1081: ret = get_errno(writev(arg1, arg2, arg3)); ! 1082: if((!is_error(ret)) && arg2) ! 1083: byteswap_iovec(arg2, arg3); ! 1084: return ret; ! 1085: } ! 1086: ! 1087: long do_utimes(char * arg1, struct timeval * arg2) ! 1088: { ! 1089: DPRINTF("utimes(%p, %p)\n", arg1, arg2); ! 1090: if(arg2) ! 1091: { ! 1092: byteswap_timeval(arg2); ! 1093: byteswap_timeval(arg2+1); ! 1094: } ! 1095: return get_errno(utimes(arg1, arg2)); ! 1096: } ! 1097: ! 1098: long do_futimes(uint32_t arg1, struct timeval * arg2) ! 1099: { ! 1100: DPRINTF("futimes(0x%x, %p)\n", arg1, arg2); ! 1101: if(arg2) ! 1102: { ! 1103: byteswap_timeval(arg2); ! 1104: byteswap_timeval(arg2+1); ! 1105: } ! 1106: return get_errno(futimes(arg1, arg2)); ! 1107: } ! 1108: ! 1109: long do_statfs(char * arg1, struct statfs * arg2) ! 1110: { ! 1111: long ret; ! 1112: DPRINTF("statfs(%p, %p)\n", arg1, arg2); ! 1113: ret = get_errno(statfs(arg1, arg2)); ! 1114: if(!is_error(ret)) ! 1115: byteswap_statfs(arg2); ! 1116: return ret; ! 1117: } ! 1118: ! 1119: long do_fstatfs(uint32_t arg1, struct statfs* arg2) ! 1120: { ! 1121: long ret; ! 1122: DPRINTF("fstatfs(0x%x, %p)\n", ! 1123: arg1, arg2); ! 1124: ret = get_errno(fstatfs(arg1, arg2)); ! 1125: if(!is_error(ret)) ! 1126: byteswap_statfs(arg2); ! 1127: ! 1128: return ret; ! 1129: } ! 1130: ! 1131: long do_stat(char * arg1, struct stat * arg2) ! 1132: { ! 1133: long ret; ! 1134: /* XXX: don't let the %s stay in there */ ! 1135: DPRINTF("stat(%s, %p)\n", arg1, arg2); ! 1136: ret = get_errno(stat(arg1, arg2)); ! 1137: if(!is_error(ret)) ! 1138: byteswap_stat(arg2); ! 1139: return ret; ! 1140: } ! 1141: ! 1142: long do_fstat(uint32_t arg1, struct stat * arg2) ! 1143: { ! 1144: long ret; ! 1145: DPRINTF("fstat(0x%x, %p)\n", arg1, arg2); ! 1146: ret = get_errno(fstat(arg1, arg2)); ! 1147: if(!is_error(ret)) ! 1148: byteswap_stat(arg2); ! 1149: return ret; ! 1150: } ! 1151: ! 1152: long do_lstat(char * arg1, struct stat * arg2) ! 1153: { ! 1154: long ret; ! 1155: /* XXX: don't let the %s stay in there */ ! 1156: DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2); ! 1157: ret = get_errno(lstat(arg1, arg2)); ! 1158: if(!is_error(ret)) ! 1159: byteswap_stat(arg2); ! 1160: return ret; ! 1161: } ! 1162: ! 1163: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4) ! 1164: { ! 1165: long ret; ! 1166: DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4); ! 1167: if(arg4) ! 1168: tswap32s((uint32_t *)arg4); ! 1169: ret = get_errno(getdirentries(arg1, arg2, arg3, arg4)); ! 1170: if(arg4) ! 1171: tswap32s((uint32_t *)arg4); ! 1172: if(!is_error(ret)) ! 1173: byteswap_dirents(arg2, ret); ! 1174: return ret; ! 1175: } ! 1176: ! 1177: long do_lseek(void *cpu_env, int num) ! 1178: { ! 1179: long ret; ! 1180: int i = 0; ! 1181: uint32_t arg1 = get_int_arg(&i, cpu_env); ! 1182: uint64_t offset = get_int64_arg(&i, cpu_env); ! 1183: uint32_t arg3 = get_int_arg(&i, cpu_env); ! 1184: uint64_t r = lseek(arg1, offset, arg3); ! 1185: #ifdef TARGET_I386 ! 1186: /* lowest word in eax, highest in edx */ ! 1187: ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */ ! 1188: ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ; ! 1189: #elif defined TARGET_PPC ! 1190: ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */ ! 1191: ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ; ! 1192: #else ! 1193: qerror("64 bit ret value on your arch?"); ! 1194: #endif ! 1195: return get_errno(ret); ! 1196: } ! 1197: ! 1198: void no_swap(void * oldp, int size) ! 1199: { ! 1200: } ! 1201: ! 1202: void sysctl_tswap32s(void * oldp, int size) ! 1203: { ! 1204: tswap32s(oldp); ! 1205: } ! 1206: ! 1207: void bswap_oid(uint32_t * oldp, int size) ! 1208: { ! 1209: int count = size / sizeof(int); ! 1210: int i = 0; ! 1211: do { tswap32s(oldp + i); } while (++i < count); ! 1212: } ! 1213: ! 1214: void sysctl_usrstack(uint32_t * oldp, int size) ! 1215: { ! 1216: DPRINTF("sysctl_usrstack: 0x%x\n", *oldp); ! 1217: tswap32s(oldp); ! 1218: } ! 1219: ! 1220: void sysctl_ncpu(uint32_t * ncpu, int size) ! 1221: { ! 1222: *ncpu = 0x1; ! 1223: DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu); ! 1224: tswap32s(ncpu); ! 1225: } ! 1226: ! 1227: void sysctl_exec(char * exec, int size) ! 1228: { ! 1229: DPRINTF("sysctl_exec: %s\n", exec); ! 1230: } ! 1231: ! 1232: void sysctl_translate(char * exec, int size) ! 1233: { ! 1234: DPRINTF("sysctl_translate: %s\n", exec); ! 1235: } ! 1236: ! 1237: struct sysctl_dir { ! 1238: int num; ! 1239: const char * name; ! 1240: void (*swap_func)(void *, int); ! 1241: struct sysctl_dir *childs; ! 1242: }; ! 1243: ! 1244: #define ENTRYD(num, name, childs) { num, name, NULL, childs } ! 1245: #define ENTRYE(num, name, func) { num, name, (void (*)(void *, int))func, NULL } ! 1246: struct sysctl_dir sysctls_unspec[] = { ! 1247: ENTRYE(3, "oip", bswap_oid), ! 1248: { 0, NULL, NULL, NULL } ! 1249: }; ! 1250: ! 1251: struct sysctl_dir sysctls_kern[] = { ! 1252: ENTRYE(KERN_TRANSLATE, "translate", sysctl_translate), /* 44 */ ! 1253: ENTRYE(KERN_EXEC, "exec", sysctl_exec), /* 45 */ ! 1254: ENTRYE(KERN_USRSTACK32, "KERN_USRSTACK32", sysctl_usrstack), /* 35 */ ! 1255: ENTRYE(KERN_SHREG_PRIVATIZABLE, "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */ ! 1256: { 0, NULL, NULL, NULL } ! 1257: }; ! 1258: ! 1259: struct sysctl_dir sysctls_hw[] = { ! 1260: ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s), ! 1261: ENTRYE(104, "104", no_swap), ! 1262: ENTRYE(105, "105", no_swap), ! 1263: { 0, NULL, NULL, NULL } ! 1264: }; ! 1265: ! 1266: struct sysctl_dir sysctls[] = { ! 1267: ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec), ! 1268: ENTRYD(CTL_KERN, "kern", sysctls_kern), ! 1269: ENTRYD(CTL_HW, "hw", sysctls_hw ), ! 1270: { 0, NULL, NULL, NULL } ! 1271: }; ! 1272: ! 1273: #undef ENTRYE ! 1274: #undef ENTRYD ! 1275: ! 1276: static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt) ! 1277: { ! 1278: if(!sysctl_elmt) ! 1279: return NULL; ! 1280: for(; sysctl_elmt->name != NULL ; sysctl_elmt++) { ! 1281: if(sysctl_elmt->num == mib) ! 1282: return sysctl_elmt; ! 1283: } ! 1284: return NULL; ! 1285: } ! 1286: ! 1287: static inline long bswap_syctl(int * mib, int count, void *buf, int size) ! 1288: { ! 1289: int i; ! 1290: struct sysctl_dir * sysctl = sysctls; ! 1291: struct sysctl_dir * ret = NULL; ! 1292: ! 1293: for(i = 0; i < count; i++) { ! 1294: ! 1295: if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) { ! 1296: gemu_log("bswap_syctl: can't find mib %d\n", mib[i]); ! 1297: return -ENOTDIR; ! 1298: } ! 1299: if(!(sysctl = sysctl->childs)) ! 1300: break; ! 1301: } ! 1302: ! 1303: if(ret->childs) ! 1304: qerror("we shouldn't have a directory element\n"); ! 1305: ! 1306: ret->swap_func(buf, size); ! 1307: return 0; ! 1308: } ! 1309: ! 1310: static inline void print_syctl(int * mib, int count) ! 1311: { ! 1312: int i; ! 1313: struct sysctl_dir * sysctl = sysctls; ! 1314: struct sysctl_dir * ret = NULL; ! 1315: ! 1316: for(i = 0; i < count; i++) { ! 1317: if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){ ! 1318: gemu_log("print_syctl: can't find mib %d\n", mib[i]); ! 1319: return; ! 1320: } ! 1321: DPRINTF("%s.", sysctl->name); ! 1322: if(!(sysctl = sysctl->childs)) ! 1323: break; ! 1324: } ! 1325: DPRINTF("\n"); ! 1326: } ! 1327: ! 1328: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */) ! 1329: { ! 1330: long ret = 0; ! 1331: int i; ! 1332: DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n", ! 1333: name, namelen, oldp, oldlenp, newp, newlen); ! 1334: if(name) { ! 1335: i = 0; ! 1336: do { tswap32s( name + i); } while (++i < namelen); ! 1337: print_syctl(name, namelen); ! 1338: //bswap_syctl(name, namelen, newp, newlen); ! 1339: tswap32s((uint32_t*)oldlenp); ! 1340: } ! 1341: ! 1342: if(name) /* Sometimes sysctl is called with no arg1, ignore */ ! 1343: ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen)); ! 1344: ! 1345: if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) { ! 1346: return -ENOTDIR; ! 1347: } ! 1348: if(name) { ! 1349: //bswap_syctl(name, namelen, newp, newlen); ! 1350: tswap32s((uint32_t*)oldlenp); ! 1351: ! 1352: i = 0; ! 1353: do { tswap32s( name + i); } while (++i < namelen); ! 1354: } ! 1355: return ret; ! 1356: } ! 1357: ! 1358: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5) ! 1359: { ! 1360: struct attrlist * attrlist = (void *)arg2; ! 1361: long ret; ! 1362: ! 1363: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__) ! 1364: gemu_log("SYS_getdirentriesattr unimplemented\n"); ! 1365: return -ENOTSUP; ! 1366: #endif ! 1367: /* XXX: don't let the %s stay in there */ ! 1368: DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n", ! 1369: (char *)arg1, arg2, arg3, arg4, arg5); ! 1370: ! 1371: if(arg2) /* XXX: We should handle that in a copy especially ! 1372: if the structure is not writable */ ! 1373: byteswap_attrlist(attrlist); ! 1374: ! 1375: ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5)); ! 1376: ! 1377: if(!is_error(ret)) ! 1378: { ! 1379: byteswap_attrbuf((void *)arg3, attrlist); ! 1380: byteswap_attrlist(attrlist); ! 1381: } ! 1382: return ret; ! 1383: } ! 1384: ! 1385: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8) ! 1386: { ! 1387: DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n", ! 1388: arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); ! 1389: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__) ! 1390: qerror("SYS_getdirentriesattr unimplemented\n"); ! 1391: #endif ! 1392: ! 1393: return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4, ! 1394: (unsigned long *)arg5, (unsigned long *)arg6, ! 1395: (unsigned long *)arg7, arg8)); ! 1396: } ! 1397: ! 1398: static inline void bswap_flock(struct flock *f) ! 1399: { ! 1400: tswap64s(&f->l_start); ! 1401: tswap64s(&f->l_len); ! 1402: tswap32s(&f->l_pid); ! 1403: tswap16s(&f->l_type); ! 1404: tswap16s(&f->l_whence); ! 1405: } ! 1406: ! 1407: static inline void bswap_fstore(struct fstore *f) ! 1408: { ! 1409: tswap32s(&f->fst_flags); ! 1410: tswap32s(&f->fst_posmode); ! 1411: tswap64s(&f->fst_offset); ! 1412: tswap64s(&f->fst_length); ! 1413: tswap64s(&f->fst_bytesalloc); ! 1414: } ! 1415: ! 1416: static inline void bswap_radvisory(struct radvisory *f) ! 1417: { ! 1418: tswap64s(&f->ra_offset); ! 1419: tswap32s(&f->ra_count); ! 1420: } ! 1421: ! 1422: static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f) ! 1423: { ! 1424: tswap64s(&f->fbt_offset); ! 1425: tswap32s((uint32_t*)&f->fbt_length); ! 1426: tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */ ! 1427: } ! 1428: ! 1429: static inline void bswap_log2phys(struct log2phys *f) ! 1430: { ! 1431: tswap32s(&f->l2p_flags); ! 1432: tswap64s(&f->l2p_contigbytes); ! 1433: tswap64s(&f->l2p_devoffset); ! 1434: } ! 1435: ! 1436: static inline void bswap_fcntl_arg(int cmd, void * arg) ! 1437: { ! 1438: switch(cmd) ! 1439: { ! 1440: case F_DUPFD: ! 1441: case F_GETFD: ! 1442: case F_SETFD: ! 1443: case F_GETFL: ! 1444: case F_SETFL: ! 1445: case F_GETOWN: ! 1446: case F_SETOWN: ! 1447: case F_SETSIZE: ! 1448: case F_RDAHEAD: ! 1449: case F_FULLFSYNC: ! 1450: break; ! 1451: case F_GETLK: ! 1452: case F_SETLK: ! 1453: case F_SETLKW: ! 1454: bswap_flock(arg); ! 1455: break; ! 1456: case F_PREALLOCATE: ! 1457: bswap_fstore(arg); ! 1458: break; ! 1459: case F_RDADVISE: ! 1460: bswap_radvisory(arg); ! 1461: break; ! 1462: case F_READBOOTSTRAP: ! 1463: case F_WRITEBOOTSTRAP: ! 1464: bswap_fbootstraptransfer(arg); ! 1465: break; ! 1466: case F_LOG2PHYS: ! 1467: bswap_log2phys(arg); ! 1468: break; ! 1469: default: ! 1470: gemu_log("unknow cmd in fcntl\n"); ! 1471: } ! 1472: } ! 1473: ! 1474: long do_fcntl(int fd, int cmd, int arg) ! 1475: { ! 1476: long ret; ! 1477: bswap_fcntl_arg(cmd, (void *)arg); ! 1478: ret = get_errno(fcntl(fd, cmd, arg)); ! 1479: if(!is_error(ret)) ! 1480: bswap_fcntl_arg(cmd, (void *)arg); ! 1481: return ret; ! 1482: } ! 1483: ! 1484: long no_syscall(void *cpu_env, int num) ! 1485: { ! 1486: /* XXX: We should probably fordward it to the host kernel */ ! 1487: qerror("no unix syscall %d\n", num); ! 1488: /* not reached */ ! 1489: return -1; ! 1490: } ! 1491: ! 1492: long unimpl_unix_syscall(void *cpu_env, int num) ! 1493: { ! 1494: if( (num < 0) || (num > SYS_MAXSYSCALL-1) ) ! 1495: qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1); ! 1496: ! 1497: gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num); ! 1498: gdb_handlesig (cpu_env, SIGTRAP); ! 1499: exit(-1); ! 1500: } ! 1501: ! 1502: long do_unix_syscall(void *cpu_env, int num) ! 1503: { ! 1504: long ret = 0; ! 1505: ! 1506: DPRINTF("unix syscall %d: " , num); ! 1507: ! 1508: if( (num < 0) || (num > SYS_MAXSYSCALL-1) ) ! 1509: qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1); ! 1510: ! 1511: DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" ); ! 1512: ret = unix_syscall_table[num].function(cpu_env, num); ! 1513: ! 1514: if(!(unix_syscall_table[num].call_type & CALL_NOERRNO)) ! 1515: ret = get_errno(ret); ! 1516: ! 1517: DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret); ! 1518: return ret; ! 1519: } ! 1520: ! 1521: /* ------------------------------------------------------------ ! 1522: syscall_init ! 1523: */ ! 1524: void syscall_init(void) ! 1525: { ! 1526: /* Nothing yet */ ! 1527: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.