?? syscall.c
字號:
/* * Darwin syscalls * * Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2006 Pierre d'Herbemont * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <mach/host_info.h>#include <mach/mach.h>#include <mach/mach_time.h>#include <mach/message.h>#include <pthread.h>#include <dirent.h>#include <sys/stat.h>#include <sys/syscall.h>#include <sys/sysctl.h>#include <sys/types.h>#include <unistd.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/dirent.h>#include <sys/uio.h>#include <sys/termios.h>#include <sys/ptrace.h>#include <net/if.h>#include <sys/param.h>#include <sys/mount.h>#include <sys/attr.h>#include <mach/ndr.h>#include <mach/mig_errors.h>#include <sys/xattr.h>#include "qemu.h"//#define DEBUG_SYSCALL#ifdef DEBUG_SYSCALL# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1# define DEBUG_BEGIN_ENABLE __DEBUG_qemu_user_force_enable = 1;# define DEBUG_END_ENABLE __DEBUG_qemu_user_force_enable = 0;# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0# define DEBUG_ENABLE_ALL() static int __DEBUG_qemu_user_force_enable = 1 DEBUG_ENABLE_ALL();# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \ if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \ } while(0)#else# define DEBUG_FORCE_ENABLE_LOCAL()# define DEBUG_BEGIN_ENABLE# define DEBUG_END_ENABLE# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)#endifenum { bswap_out = 0, bswap_in = 1};extern const char *interp_prefix;static inline long get_errno(long ret){ if (ret == -1) return -errno; else return ret;}static inline int is_error(long ret){ return (unsigned long)ret >= (unsigned long)(-4096);}/* ------------------------------------------------------------ Mach syscall handling*/void static inline print_description_msg_header(mach_msg_header_t *hdr){ char *name = NULL; int i; struct { int number; char *name; } msg_name[] = { /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */ { 200, "host_info" }, { 202, "host_page_size" }, { 206, "host_get_clock_service" }, { 206, "host_get_clock_service" }, { 206, "host_get_clock_service" }, { 306, "host_get_clock_service" }, { 3204, "mach_port_allocate" }, { 3206, "mach_port_deallocate" }, { 3404, "mach_ports_lookup" }, { 3409, "mach_task_get_special_port" }, { 3414, "mach_task_get_exception_ports" }, { 3418, "mach_semaphore_create" }, { 3504, "mach_semaphore_create" }, { 3509, "mach_semaphore_create" }, { 3518, "semaphore_create" }, { 3616, "thread_policy" }, { 3801, "vm_allocate" }, { 3802, "vm_deallocate" }, { 3802, "vm_deallocate" }, { 3803, "vm_protect" }, { 3812, "vm_map" }, { 4241776, "lu_message_send_id" }, /* lookupd */ { 4241876, "lu_message_reply_id" }, /* lookupd */ }; for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) { if(msg_name[i].number == hdr->msgh_id) { name = msg_name[i].name; break; } } if(!name) DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id); else DPRINTF("%s\n", name);#if 0 DPRINTF("Bits: %8x\n", hdr->msgh_bits); DPRINTF("Size: %8x\n", hdr->msgh_size); DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port); DPRINTF("Locl: %8x\n", hdr->msgh_local_port); DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved); DPRINTF("Id : %8x\n", hdr->msgh_id); NDR_record_t *ndr = (NDR_record_t *)(hdr + 1); DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr); DPRINTF("%d %d %d %d %d %d %d %d\n", ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding, ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);#endif}static inline void print_mach_msg_return(mach_msg_return_t ret){ int i, found = 0;#define MACH_MSG_RET(msg) { msg, #msg } struct { int code; char *name; } msg_name[] = { /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */ /* send message */ MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL), MACH_MSG_RET(MACH_SEND_NO_BUFFER), MACH_MSG_RET(MACH_SEND_INVALID_DATA), MACH_MSG_RET(MACH_SEND_INVALID_HEADER), MACH_MSG_RET(MACH_SEND_INVALID_DEST), MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY), MACH_MSG_RET(MACH_SEND_INVALID_REPLY), MACH_MSG_RET(MACH_SEND_INVALID_TRAILER), MACH_MSG_RET(MACH_SEND_INVALID_MEMORY), MACH_MSG_RET(MACH_SEND_INVALID_RIGHT), MACH_MSG_RET(MACH_SEND_INVALID_TYPE), MACH_MSG_RET(MACH_SEND_INTERRUPTED), MACH_MSG_RET(MACH_SEND_TIMED_OUT), MACH_MSG_RET(MACH_RCV_BODY_ERROR), MACH_MSG_RET(MACH_RCV_HEADER_ERROR), MACH_MSG_RET(MACH_RCV_IN_SET), MACH_MSG_RET(MACH_RCV_INTERRUPTED), MACH_MSG_RET(MACH_RCV_INVALID_DATA), MACH_MSG_RET(MACH_RCV_INVALID_NAME), MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY), MACH_MSG_RET(MACH_RCV_INVALID_TRAILER), MACH_MSG_RET(MACH_RCV_INVALID_TYPE), MACH_MSG_RET(MACH_RCV_PORT_CHANGED), MACH_MSG_RET(MACH_RCV_PORT_DIED), MACH_MSG_RET(MACH_RCV_SCATTER_SMALL), MACH_MSG_RET(MACH_RCV_TIMED_OUT), MACH_MSG_RET(MACH_RCV_TOO_LARGE) };#undef MACH_MSG_RET if( ret == MACH_MSG_SUCCESS) DPRINTF("MACH_MSG_SUCCESS\n"); else { for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) { if(msg_name[i].code == ret) { DPRINTF("%s\n", msg_name[i].name); found = 1; break; } } if(!found) qerror("unknow mach message ret code %d\n", ret); }}static inline void swap_mach_msg_header(mach_msg_header_t *hdr){ hdr->msgh_bits = tswap32(hdr->msgh_bits); hdr->msgh_size = tswap32(hdr->msgh_size); hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port); hdr->msgh_local_port = tswap32(hdr->msgh_local_port); hdr->msgh_reserved = tswap32(hdr->msgh_reserved); hdr->msgh_id = tswap32(hdr->msgh_id);}struct complex_msg { mach_msg_header_t hdr; mach_msg_body_t body;};static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap){ mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1); int i,j; if(bswap == bswap_in) tswap32s(&complex_msg->body.msgh_descriptor_count); DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count); for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) { switch(descr->type) { case MACH_MSG_PORT_DESCRIPTOR: tswap32s(&descr->name); descr++; break; case MACH_MSG_OOL_DESCRIPTOR: { mach_msg_ool_descriptor_t *ool = (void *)descr; tswap32s((uint32_t *)&ool->address); tswap32s(&ool->size); descr = (mach_msg_port_descriptor_t *)(ool+1); break; } case MACH_MSG_OOL_PORTS_DESCRIPTOR: { mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr; mach_port_name_t * port_names; if(bswap == bswap_in) { tswap32s((uint32_t *)&ool_ports->address); tswap32s(&ool_ports->count); } port_names = ool_ports->address; for(j = 0; j < ool_ports->count; j++) tswap32s(&port_names[j]); if(bswap == bswap_out) { tswap32s((uint32_t *)&ool_ports->address); tswap32s(&ool_ports->count); } descr = (mach_msg_port_descriptor_t *)(ool_ports+1); break; } default: qerror("unknow mach msg descriptor type %x\n", descr->type); } } if(bswap == bswap_out) tswap32s(&complex_msg->body.msgh_descriptor_count);}static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap){ if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX) swap_mach_msg_body((struct complex_msg *)hdr, bswap); swap_mach_msg_header(hdr); if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX) swap_mach_msg_body((struct complex_msg *)hdr, bswap);}static inline uint32_t target_mach_msg_trap( mach_msg_header_t *hdr, uint32_t options, uint32_t send_size, uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify){ extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, mach_msg_size_t, mach_msg_size_t, mach_port_t, mach_msg_timeout_t, mach_port_t); mach_msg_audit_trailer_t *trailer; mach_msg_id_t msg_id; uint32_t ret = 0; int i; swap_mach_msg(hdr, bswap_in); msg_id = hdr->msgh_id; print_description_msg_header(hdr); ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify); print_mach_msg_return(ret); if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) ) { /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should probably always bswap it */ /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in natural_t units but according to xnu/osfmk/mach/message.h: "The size of the message must be specified in bytes" */ trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size); /* XXX: Should probably do that based on the option asked by the sender, but dealing with kernel answer seems more sound */ switch(trailer->msgh_trailer_size) { case sizeof(mach_msg_audit_trailer_t): for(i = 0; i < 8; i++) tswap32s(&trailer->msgh_audit.val[i]); /* Fall in mach_msg_security_trailer_t case */ case sizeof(mach_msg_security_trailer_t): tswap32s(&trailer->msgh_sender.val[0]); tswap32s(&trailer->msgh_sender.val[1]); /* Fall in mach_msg_seqno_trailer_t case */ case sizeof(mach_msg_seqno_trailer_t): tswap32s(&trailer->msgh_seqno); /* Fall in mach_msg_trailer_t case */ case sizeof(mach_msg_trailer_t): tswap32s(&trailer->msgh_trailer_type); tswap32s(&trailer->msgh_trailer_size); break; case 0: /* Safer not to byteswap, but probably wrong */ break; default: qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size); break; } } /* Special message handling */ switch (msg_id) { case 200: /* host_info */ { mig_reply_error_t *err = (mig_reply_error_t *)hdr; struct { uint32_t unknow1; uint32_t max_cpus; uint32_t avail_cpus; uint32_t memory_size; uint32_t cpu_type; uint32_t cpu_subtype; } *data = (void *)(err+1); DPRINTF("maxcpu = 0x%x\n", data->max_cpus); DPRINTF("numcpu = 0x%x\n", data->avail_cpus); DPRINTF("memsize = 0x%x\n", data->memory_size);#if defined(TARGET_I386) data->cpu_type = CPU_TYPE_I386; DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type); data->cpu_subtype = CPU_SUBTYPE_PENT; DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);#elif defined(TARGET_PPC) data->cpu_type = CPU_TYPE_POWERPC; DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -