diff options
author | Andreas Färber <afaerber@suse.de> | 2012-04-16 04:31:11 +0000 |
---|---|---|
committer | Andreas Färber <andreas.faerber@web.de> | 2012-05-01 00:17:27 +0200 |
commit | 0adb124659cfadf9f0b5c99874c476116f0cf74f (patch) | |
tree | f4f820e8ddb4b0889138712043261ac4ca390696 | |
parent | 148210301e334694badcc8ae72ecb522c6d7bac6 (diff) |
Drop darwin-user
It's been orphaned, not compiling for a long time and despite Apple's
drop of their Rosetta ppc emulation technology with Mac OS X Lion no one
has stepped up to fix it.
Testing necessary changes wrt QOM'ification thus is impossible, so we
might as well remove it completely.
Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | MAINTAINERS | 5 | ||||
-rw-r--r-- | Makefile.target | 28 | ||||
-rwxr-xr-x | configure | 25 | ||||
-rw-r--r-- | darwin-user/commpage.c | 357 | ||||
-rw-r--r-- | darwin-user/ioctls.h | 4 | ||||
-rw-r--r-- | darwin-user/ioctls_types.h | 1 | ||||
-rw-r--r-- | darwin-user/machload.c | 902 | ||||
-rw-r--r-- | darwin-user/main.c | 1027 | ||||
-rw-r--r-- | darwin-user/mmap.c | 409 | ||||
-rw-r--r-- | darwin-user/qemu.h | 178 | ||||
-rw-r--r-- | darwin-user/signal.c | 452 | ||||
-rw-r--r-- | darwin-user/syscall.c | 1566 | ||||
-rw-r--r-- | darwin-user/syscalls.h | 384 | ||||
-rw-r--r-- | default-configs/i386-darwin-user.mak | 1 | ||||
-rw-r--r-- | default-configs/ppc-darwin-user.mak | 3 | ||||
-rw-r--r-- | qemu-doc.texi | 90 | ||||
-rw-r--r-- | qemu-tech.texi | 3 |
17 files changed, 1 insertions, 5434 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index cce37e797f..c58465d3f7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -570,11 +570,6 @@ M: Blue Swirl <blauwirbel@gmail.com> S: Maintained F: bsd-user/ -Darwin user -M: qemu-devel@nongnu.org -S: Orphan -F: darwin-user/ - Linux user M: Riku Voipio <riku.voipio@iki.fi> S: Maintained diff --git a/Makefile.target b/Makefile.target index 1cf694372c..7d68a25e46 100644 --- a/Makefile.target +++ b/Makefile.target @@ -162,34 +162,6 @@ obj-y += $(libobj-y) endif #CONFIG_LINUX_USER ######################################################### -# Darwin user emulator target - -ifdef CONFIG_DARWIN_USER - -$(call set-vpath, $(SRC_PATH)/darwin-user) - -QEMU_CFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH) - -# Leave some space for the regular program loading zone -LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000 - -LIBS+=-lmx - -obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \ - gdbstub.o user-exec.o - -obj-i386-y += ioport-user.o - -$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS) - -obj-y += $(addprefix ../, $(universal-obj-y)) -obj-y += $(addprefix ../libuser/, $(user-obj-y)) -obj-y += $(addprefix ../libdis-user/, $(libdis-y)) -obj-y += $(libobj-y) - -endif #CONFIG_DARWIN_USER - -######################################################### # BSD user emulator target ifdef CONFIG_BSD_USER @@ -173,7 +173,6 @@ profiler="no" cocoa="no" softmmu="yes" linux_user="no" -darwin_user="no" bsd_user="no" guest_base="" uname_release="" @@ -424,7 +423,6 @@ Darwin) else QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS" fi - darwin_user="yes" cocoa="yes" audio_drv_list="coreaudio" audio_possible_drivers="coreaudio sdl fmod" @@ -728,17 +726,12 @@ for opt do --disable-user) linux_user="no" ; bsd_user="no" ; - darwin_user="no" ;; --enable-user) ;; --disable-linux-user) linux_user="no" ;; --enable-linux-user) linux_user="yes" ;; - --disable-darwin-user) darwin_user="no" - ;; - --enable-darwin-user) darwin_user="yes" - ;; --disable-bsd-user) bsd_user="no" ;; --enable-bsd-user) bsd_user="yes" @@ -967,10 +960,6 @@ unicore32-linux-user \ s390x-linux-user \ " fi -# the following are Darwin specific -if [ "$darwin_user" = "yes" ] ; then - default_target_list="$default_target_list i386-darwin-user ppc-darwin-user " -fi # the following are BSD specific if [ "$bsd_user" = "yes" ] ; then default_target_list="${default_target_list}\ @@ -1072,8 +1061,6 @@ echo " --enable-user enable supported user emulation targets" echo " --disable-user disable all user emulation targets" echo " --enable-linux-user enable all linux usermode emulation targets" echo " --disable-linux-user disable all linux usermode emulation targets" -echo " --enable-darwin-user enable all darwin usermode emulation targets" -echo " --disable-darwin-user disable all darwin usermode emulation targets" echo " --enable-bsd-user enable all BSD usermode emulation targets" echo " --disable-bsd-user disable all BSD usermode emulation targets" echo " --enable-guest-base enable GUEST_BASE support for usermode" @@ -3472,7 +3459,6 @@ esac target_softmmu="no" target_user_only="no" target_linux_user="no" -target_darwin_user="no" target_bsd_user="no" case "$target" in ${target_arch2}-softmmu) @@ -3486,14 +3472,6 @@ case "$target" in target_user_only="yes" target_linux_user="yes" ;; - ${target_arch2}-darwin-user) - if test "$darwin" != "yes" ; then - echo "ERROR: Target '$target' is only available on a Darwin host" - exit 1 - fi - target_user_only="yes" - target_darwin_user="yes" - ;; ${target_arch2}-bsd-user) if test "$bsd" != "yes" ; then echo "ERROR: Target '$target' is only available on a BSD host" @@ -3747,9 +3725,6 @@ fi if test "$target_linux_user" = "yes" ; then echo "CONFIG_LINUX_USER=y" >> $config_target_mak fi -if test "$target_darwin_user" = "yes" ; then - echo "CONFIG_DARWIN_USER=y" >> $config_target_mak -fi list="" if test ! -z "$gdb_xml_files" ; then for x in $gdb_xml_files; do diff --git a/darwin-user/commpage.c b/darwin-user/commpage.c deleted file mode 100644 index cc29bddd95..0000000000 --- a/darwin-user/commpage.c +++ /dev/null @@ -1,357 +0,0 @@ - /* - * Commpage syscalls - * - * 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, see <http://www.gnu.org/licenses/>. - */ -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> - -#include <mach/message.h> -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <sys/time.h> -#include <sys/mman.h> -#include <libkern/OSAtomic.h> - -#include "qemu.h" - -//#define DEBUG_COMMPAGE - -#ifdef DEBUG_COMMPAGE -# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0) -#else -# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0) -#endif - -/******************************************************************** - * Commpage definitions - */ -#ifdef TARGET_I386 -/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */ -# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */ -# define COMMPAGE_SIZE (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */ -#elif defined(TARGET_PPC) -/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */ -# define COMMPAGE_START (-8*4096) -# define COMMPAGE_SIZE (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */ -#endif - -void do_compare_and_swap32(void *cpu_env, int num); -void do_compare_and_swap64(void *cpu_env, int num); -void do_add_atomic_word32(void *cpu_env, int num); -void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1); -void do_nanotime(void *cpu_env, int num); - -void unimpl_commpage(void *cpu_env, int num); - -typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, - uint32_t arg8); -typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1, - uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5, - uint32_t arg6, uint32_t arg7, uint32_t arg8); - -#define HAS_PTR 0x10 -#define NO_PTR 0x20 -#define CALL_DIRECT 0x1 -#define CALL_INDIRECT 0x2 - -#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \ - { #name, offset, nargs, options, (commpage_8args_function_t)func } - -struct commpage_entry { - char * name; - int offset; - int nargs; - char options; - commpage_8args_function_t function; -}; - -static inline int commpage_code_num(struct commpage_entry *entry) -{ - if((entry->options & HAS_PTR)) - return entry->offset + 4; - else - return entry->offset; -} - -static inline int commpage_is_indirect(struct commpage_entry *entry) -{ - return !(entry->options & CALL_DIRECT); -} - -/******************************************************************** - * Commpage entry - */ -static struct commpage_entry commpage_entries[] = -{ - COMMPAGE_ENTRY(compare_and_swap32, 0, 0x080, do_compare_and_swap32, CALL_INDIRECT | HAS_PTR), - COMMPAGE_ENTRY(compare_and_swap64, 0, 0x0c0, do_compare_and_swap64, CALL_INDIRECT | HAS_PTR), - COMMPAGE_ENTRY(enqueue, 0, 0x100, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(dequeue, 0, 0x140, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(memory_barrier, 0, 0x180, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(add_atomic_word32, 0, 0x1a0, do_add_atomic_word32, CALL_INDIRECT | HAS_PTR), - COMMPAGE_ENTRY(add_atomic_word64, 0, 0x1c0, unimpl_commpage, CALL_INDIRECT | HAS_PTR), - - COMMPAGE_ENTRY(mach_absolute_time, 0, 0x200, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(spinlock_try, 1, 0x220, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(spinlock_lock, 1, 0x260, OSSpinLockLock, CALL_DIRECT), - COMMPAGE_ENTRY(spinlock_unlock, 1, 0x2a0, OSSpinLockUnlock, CALL_DIRECT), - COMMPAGE_ENTRY(pthread_getspecific, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(gettimeofday, 1, 0x2e0, do_cgettimeofday, CALL_INDIRECT), - COMMPAGE_ENTRY(sys_dcache_flush, 0, 0x4e0, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(pthread_self, 0, 0x580, unimpl_commpage, CALL_INDIRECT), - - COMMPAGE_ENTRY(relinquish, 0, 0x5c0, unimpl_commpage, CALL_INDIRECT), - -#ifdef TARGET_I386 - COMMPAGE_ENTRY(bts, 0, 0x5e0, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(btc, 0, 0x5f0, unimpl_commpage, CALL_INDIRECT), -#endif - - COMMPAGE_ENTRY(bzero, 2, 0x600, bzero, CALL_DIRECT), - COMMPAGE_ENTRY(bcopy, 3, 0x780, bcopy, CALL_DIRECT), - COMMPAGE_ENTRY(memcpy, 3, 0x7a0, memcpy, CALL_DIRECT), - -#ifdef TARGET_I386 - COMMPAGE_ENTRY(old_nanotime, 0, 0xf80, do_nanotime, CALL_INDIRECT), - COMMPAGE_ENTRY(memset_pattern, 0, 0xf80, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(long_copy, 0, 0x1200, unimpl_commpage, CALL_INDIRECT), - - COMMPAGE_ENTRY(sysintegrity, 0, 0x1600, unimpl_commpage, CALL_INDIRECT), - - COMMPAGE_ENTRY(nanotime, 0, 0x1700, do_nanotime, CALL_INDIRECT), -#elif TARGET_PPC - COMMPAGE_ENTRY(compare_and_swap32b, 0, 0xf80, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(compare_and_swap64b, 0, 0xfc0, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(memset_pattern, 0, 0x1000, unimpl_commpage, CALL_INDIRECT), - COMMPAGE_ENTRY(bigcopy, 0, 0x1140, unimpl_commpage, CALL_INDIRECT), -#endif -}; - - -/******************************************************************** - * Commpage backdoor - */ -static inline void print_commpage_entry(struct commpage_entry entry) -{ - printf("@0x%x %s\n", entry.offset, entry.name); -} - -static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry) -{ -#ifdef TARGET_I386 - char * commpage = (char*)(COMMPAGE_START+entry.offset); - int c = 0; - if(entry.options & HAS_PTR) - { - commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff; - commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff; - commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff; - commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff; - } - commpage[c++] = 0xcd; - commpage[c++] = 0x79; /* int 0x79 */ - commpage[c++] = 0xc3; /* ret */ -#else - qerror("can't install the commpage on this arch\n"); -#endif -} - -/******************************************************************** - * Commpage initialization - */ -void commpage_init(void) -{ -#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(_ARCH_PPC) ^ defined(TARGET_PPC)) - int i; - void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE, - PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0); - if((int)commpage != COMMPAGE_START) - qerror("can't allocate the commpage\n"); - - bzero(commpage, COMMPAGE_SIZE); - - /* XXX: commpage data not handled */ - - for(i = 0; i < ARRAY_SIZE(commpage_entries); i++) - install_commpage_backdoor_for_entry(commpage_entries[i]); -#else - /* simply map our pages so they can be executed - XXX: we don't really want to do that since in the ppc on ppc situation we may - not able to run commpages host optimized instructions (like G5's on a G5), - hence this is sometimes a broken fix. */ - page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID); -#endif -} - -/******************************************************************** - * Commpage implementation - */ -void do_compare_and_swap32(void *cpu_env, int num) -{ -#ifdef TARGET_I386 - uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX]; - uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX]; - DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value); - - if(old == tswap32(*value)) - { - uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX]; - *value = tswap32(new); - /* set zf flag */ - ((CPUX86State*)cpu_env)->eflags |= 0x40; - } - else - { - ((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value); - /* unset zf flag */ - ((CPUX86State*)cpu_env)->eflags &= ~0x40; - } -#else - qerror("do_compare_and_swap32 unimplemented"); -#endif -} - -void do_compare_and_swap64(void *cpu_env, int num) -{ -#ifdef TARGET_I386 - /* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */ - uint64_t old, new, swapped_val; - uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI]; - old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX]; - - DPRINTF("commpage: compare_and_swap64(%" PRIx64 ",new,%p)\n", old, value); - swapped_val = tswap64(*value); - - if(old == swapped_val) - { - new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX]; - *value = tswap64(new); - /* set zf flag */ - ((CPUX86State*)cpu_env)->eflags |= 0x40; - } - else - { - ((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val); - ((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32); - /* unset zf flag */ - ((CPUX86State*)cpu_env)->eflags &= ~0x40; - } -#else - qerror("do_compare_and_swap64 unimplemented"); -#endif -} - -void do_add_atomic_word32(void *cpu_env, int num) -{ -#ifdef TARGET_I386 - uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX]; - uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX]; - uint32_t swapped_value = tswap32(*value); - - DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value); - - /* old value in EAX */ - ((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value; - *value = tswap32(swapped_value + amt); -#else - qerror("do_add_atomic_word32 unimplemented"); -#endif -} - -void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1) -{ -#ifdef TARGET_I386 - extern int __commpage_gettimeofday(struct timeval *); - DPRINTF("commpage: gettimeofday(0x%x)\n", arg1); - struct timeval *time = (struct timeval *)arg1; - int ret = __commpage_gettimeofday(time); - tswap32s((uint32_t*)&time->tv_sec); - tswap32s((uint32_t*)&time->tv_usec); - ((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */ -#else - qerror("do_gettimeofday unimplemented"); -#endif -} - -void do_nanotime(void *cpu_env, int num) -{ -#ifdef TARGET_I386 - uint64_t t = mach_absolute_time(); - ((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff); - ((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff); -#else - qerror("do_nanotime unimplemented"); -#endif -} - -void unimpl_commpage(void *cpu_env, int num) -{ - qerror("qemu: commpage function 0x%x not implemented\n", num); -} - -/******************************************************************** - * do_commpage - called by the main cpu loop - */ -void -do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, - uint32_t arg8) -{ - int i, found = 0; - - arg1 = tswap32(arg1); - arg2 = tswap32(arg2); - arg3 = tswap32(arg3); - arg4 = tswap32(arg4); - arg5 = tswap32(arg5); - arg6 = tswap32(arg6); - arg7 = tswap32(arg7); - arg8 = tswap32(arg8); - - num = num-COMMPAGE_START-2; - - for(i = 0; i < ARRAY_SIZE(commpage_entries); i++) { - if( num == commpage_code_num(&commpage_entries[i]) ) - { - DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]"); - found = 1; - if(commpage_is_indirect(&commpage_entries[i])) - { - commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function; - function(cpu_env, num, arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8); - } - else - { - commpage_entries[i].function(arg1, arg2, arg3, - arg4, arg5, arg6, arg7, arg8); - } - break; - } - } - - if(!found) - { - gemu_log("qemu: commpage function 0x%x not defined\n", num); - gdb_handlesig (cpu_env, SIGTRAP); - exit(-1); - } -} diff --git a/darwin-user/ioctls.h b/darwin-user/ioctls.h deleted file mode 100644 index dc73af259c..0000000000 --- a/darwin-user/ioctls.h +++ /dev/null @@ -1,4 +0,0 @@ - /* emulated ioctl list */ - - IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios))) - IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) diff --git a/darwin-user/ioctls_types.h b/darwin-user/ioctls_types.h deleted file mode 100644 index 014561a40d..0000000000 --- a/darwin-user/ioctls_types.h +++ /dev/null @@ -1 +0,0 @@ -STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT) diff --git a/darwin-user/machload.c b/darwin-user/machload.c deleted file mode 100644 index 26dd293686..0000000000 --- a/darwin-user/machload.c +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Mach-O object file loading - * - * Copyright (c) 2006 Pierre d'Herbemont - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - */ -#include <stdio.h> -#include <sys/types.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <errno.h> -#include <unistd.h> -#include <sys/mman.h> -#include <stdlib.h> -#include <string.h> - -#include "qemu.h" -#include "disas.h" - -#include <mach-o/loader.h> -#include <mach-o/fat.h> -#include <mach-o/nlist.h> -#include <mach-o/reloc.h> -#include <mach-o/ppc/reloc.h> - -//#define DEBUG_MACHLOAD - -#ifdef DEBUG_MACHLOAD -# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0) -#else -# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0) -#endif - -# define check_mach_header(x) (x.magic == MH_CIGAM) - -extern const char *interp_prefix; - -/* we don't have a good implementation for this */ -#define DONT_USE_DYLD_SHARED_MAP - -/* Pass extra arg to DYLD for debug */ -//#define ACTIVATE_DYLD_TRACE - -//#define OVERRIDE_DYLINKER - -#ifdef OVERRIDE_DYLINKER -# ifdef TARGET_I386 -# define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld" -# else -# define DYLINKER_NAME "/usr/lib/dyld" -# endif -#endif - -/* XXX: in an include */ -struct nlist_extended -{ - union { - char *n_name; - long n_strx; - } n_un; - unsigned char n_type; - unsigned char n_sect; - short st_desc; - unsigned long st_value; - unsigned long st_size; -}; - -/* Print symbols in gdb */ -void *macho_text_sect = 0; -int macho_offset = 0; - -int load_object(const char *filename, struct target_pt_regs * regs, void ** mh); - -#ifdef TARGET_I386 -typedef struct mach_i386_thread_state { - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - unsigned int edi; - unsigned int esi; - unsigned int ebp; - unsigned int esp; - unsigned int ss; - unsigned int eflags; - unsigned int eip; - unsigned int cs; - unsigned int ds; - unsigned int es; - unsigned int fs; - unsigned int gs; -} mach_i386_thread_state_t; - -void bswap_i386_thread_state(struct mach_i386_thread_state *ts) -{ - bswap32s((uint32_t*)&ts->eax); - bswap32s((uint32_t*)&ts->ebx); - bswap32s((uint32_t*)&ts->ecx); - bswap32s((uint32_t*)&ts->edx); - bswap32s((uint32_t*)&ts->edi); - bswap32s((uint32_t*)&ts->esi); - bswap32s((uint32_t*)&ts->ebp); - bswap32s((uint32_t*)&ts->esp); - bswap32s((uint32_t*)&ts->ss); - bswap32s((uint32_t*)&ts->eflags); - bswap32s((uint32_t*)&ts->eip); - bswap32s((uint32_t*)&ts->cs); - bswap32s((uint32_t*)&ts->ds); - bswap32s((uint32_t*)&ts->es); - bswap32s((uint32_t*)&ts->fs); - bswap32s((uint32_t*)&ts->gs); -} -#define target_thread_state mach_i386_thread_state -#define TARGET_CPU_TYPE CPU_TYPE_I386 -#define TARGET_CPU_NAME "i386" -#endif - -#ifdef TARGET_PPC -struct mach_ppc_thread_state { - unsigned int srr0; /* Instruction address register (PC) */ - unsigned int srr1; /* Machine state register (supervisor) */ - unsigned int r0; - unsigned int r1; - unsigned int r2; - unsigned int r3; - unsigned int r4; - unsigned int r5; - unsigned int r6; - unsigned int r7; - unsigned int r8; - unsigned int r9; - unsigned int r10; - unsigned int r11; - unsigned int r12; - unsigned int r13; - unsigned int r14; - unsigned int r15; - unsigned int r16; - unsigned int r17; - unsigned int r18; - unsigned int r19; - unsigned int r20; - unsigned int r21; - unsigned int r22; - unsigned int r23; - unsigned int r24; - unsigned int r25; - unsigned int r26; - unsigned int r27; - unsigned int r28; - unsigned int r29; - unsigned int r30; - unsigned int r31; - - unsigned int cr; /* Condition register */ - unsigned int xer; /* User's integer exception register */ - unsigned int lr; /* Link register */ - unsigned int ctr; /* Count register */ - unsigned int mq; /* MQ register (601 only) */ - - unsigned int vrsave; /* Vector Save Register */ -}; - -void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts) -{ - bswap32s((uint32_t*)&ts->srr0); - bswap32s((uint32_t*)&ts->srr1); - bswap32s((uint32_t*)&ts->r0); - bswap32s((uint32_t*)&ts->r1); - bswap32s((uint32_t*)&ts->r2); - bswap32s((uint32_t*)&ts->r3); - bswap32s((uint32_t*)&ts->r4); - bswap32s((uint32_t*)&ts->r5); - bswap32s((uint32_t*)&ts->r6); - bswap32s((uint32_t*)&ts->r7); - bswap32s((uint32_t*)&ts->r8); - bswap32s((uint32_t*)&ts->r9); - bswap32s((uint32_t*)&ts->r10); - bswap32s((uint32_t*)&ts->r11); - bswap32s((uint32_t*)&ts->r12); - bswap32s((uint32_t*)&ts->r13); - bswap32s((uint32_t*)&ts->r14); - bswap32s((uint32_t*)&ts->r15); - bswap32s((uint32_t*)&ts->r16); - bswap32s((uint32_t*)&ts->r17); - bswap32s((uint32_t*)&ts->r18); - bswap32s((uint32_t*)&ts->r19); - bswap32s((uint32_t*)&ts->r20); - bswap32s((uint32_t*)&ts->r21); - bswap32s((uint32_t*)&ts->r22); - bswap32s((uint32_t*)&ts->r23); - bswap32s((uint32_t*)&ts->r24); - bswap32s((uint32_t*)&ts->r25); - bswap32s((uint32_t*)&ts->r26); - bswap32s((uint32_t*)&ts->r27); - bswap32s((uint32_t*)&ts->r28); - bswap32s((uint32_t*)&ts->r29); - bswap32s((uint32_t*)&ts->r30); - bswap32s((uint32_t*)&ts->r31); - - bswap32s((uint32_t*)&ts->cr); - bswap32s((uint32_t*)&ts->xer); - bswap32s((uint32_t*)&ts->lr); - bswap32s((uint32_t*)&ts->ctr); - bswap32s((uint32_t*)&ts->mq); - - bswap32s((uint32_t*)&ts->vrsave); -} - -#define target_thread_state mach_ppc_thread_state -#define TARGET_CPU_TYPE CPU_TYPE_POWERPC -#define TARGET_CPU_NAME "PowerPC" -#endif - -struct target_thread_command { - unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */ - unsigned long cmdsize; /* total size of this command */ - unsigned long flavor; /* flavor of thread state */ - unsigned long count; /* count of longs in thread state */ - struct target_thread_state state; /* thread state for this flavor */ -}; - -void bswap_tc(struct target_thread_command *tc) -{ - bswap32s((uint32_t*)(&tc->flavor)); - bswap32s((uint32_t*)&tc->count); -#if defined(TARGET_I386) - bswap_i386_thread_state(&tc->state); -#elif defined(TARGET_PPC) - bswap_ppc_thread_state(&tc->state); -#else -# error unknown TARGET_CPU_TYPE -#endif -} - -void bswap_mh(struct mach_header *mh) -{ - bswap32s((uint32_t*)(&mh->magic)); - bswap32s((uint32_t*)&mh->cputype); - bswap32s((uint32_t*)&mh->cpusubtype); - bswap32s((uint32_t*)&mh->filetype); - bswap32s((uint32_t*)&mh->ncmds); - bswap32s((uint32_t*)&mh->sizeofcmds); - bswap32s((uint32_t*)&mh->flags); -} - -void bswap_lc(struct load_command *lc) -{ - bswap32s((uint32_t*)&lc->cmd); - bswap32s((uint32_t*)&lc->cmdsize); -} - - -void bswap_fh(struct fat_header *fh) -{ - bswap32s((uint32_t*)&fh->magic); - bswap32s((uint32_t*)&fh->nfat_arch); -} - -void bswap_fa(struct fat_arch *fa) -{ - bswap32s((uint32_t*)&fa->cputype); - bswap32s((uint32_t*)&fa->cpusubtype); - bswap32s((uint32_t*)&fa->offset); - bswap32s((uint32_t*)&fa->size); - bswap32s((uint32_t*)&fa->align); -} - -void bswap_segcmd(struct segment_command *sc) -{ - bswap32s((uint32_t*)&sc->vmaddr); - bswap32s((uint32_t*)&sc->vmsize); - bswap32s((uint32_t*)&sc->fileoff); - bswap32s((uint32_t*)&sc->filesize); - bswap32s((uint32_t*)&sc->maxprot); - bswap32s((uint32_t*)&sc->initprot); - bswap32s((uint32_t*)&sc->nsects); - bswap32s((uint32_t*)&sc->flags); -} - -void bswap_symtabcmd(struct symtab_command *stc) -{ - bswap32s((uint32_t*)&stc->cmd); - bswap32s((uint32_t*)&stc->cmdsize); - bswap32s((uint32_t*)&stc->symoff); - bswap32s((uint32_t*)&stc->nsyms); - bswap32s((uint32_t*)&stc->stroff); - bswap32s((uint32_t*)&stc->strsize); -} - -void bswap_sym(struct nlist *n) -{ - bswap32s((uint32_t*)&n->n_un.n_strx); - bswap16s((uint16_t*)&n->n_desc); - bswap32s((uint32_t*)&n->n_value); -} - -int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap) -{ - int entry; - if(need_bswap) - bswap_tc(tc); -#if defined(TARGET_I386) - entry = tc->state.eip; - DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n", - tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp, - tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es, - tc->state.fs, tc->state.gs ); -#define reg_copy(reg) regs->reg = tc->state.reg - if(regs) - { - reg_copy(eax); - reg_copy(ebx); - reg_copy(ecx); - reg_copy(edx); - - reg_copy(edi); - reg_copy(esi); - - reg_copy(ebp); - reg_copy(esp); - - reg_copy(eflags); - reg_copy(eip); - /* - reg_copy(ss); - reg_copy(cs); - reg_copy(ds); - reg_copy(es); - reg_copy(fs); - reg_copy(gs);*/ - } -#undef reg_copy -#elif defined(TARGET_PPC) - entry = tc->state.srr0; -#endif - DPRINTF("load_thread: entry 0x%x\n", entry); - return entry; -} - -int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap) -{ - int size; - char * dylinker_name; - size = dc->cmdsize - sizeof(struct dylinker_command); - - if(need_bswap) - dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc); - else - dylinker_name = (char*)((dc->name.offset)+(int)dc); - -#ifdef OVERRIDE_DYLINKER - dylinker_name = DYLINKER_NAME; -#else - if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1) - qerror("can't allocate the new dylinker name\n"); -#endif - - DPRINTF("dylinker_name %s\n", dylinker_name); - return load_object(dylinker_name, NULL, NULL); -} - -int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide) -{ - unsigned long addr = sc->vmaddr; - unsigned long size = sc->filesize; - unsigned long error = 0; - - if(need_bswap) - bswap_segcmd(sc); - - if(sc->vmaddr == 0) - { - DPRINTF("load_segment: sc->vmaddr == 0 returning\n"); - return -1; - } - - if (strcmp(sc->segname, "__PAGEZERO") == 0) - { - DPRINTF("load_segment: __PAGEZERO returning\n"); - return -1; - } - - /* Right now mmap memory */ - /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */ - DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide); - - if(sc->filesize > 0) - { - int opt = 0; - - if(fixed) - opt |= MAP_FIXED; - - DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide); - - addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff); - - if(addr==-1) - qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide); - - error = addr-sc->vmaddr; - } - else - { - addr = sc->vmaddr+slide; - error = slide; - } - - if(sc->vmsize > sc->filesize) - { - addr += sc->filesize; - size = sc->vmsize-sc->filesize; - addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0); - if(addr==-1) - qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide); - } - - return error; -} - -void *load_data(int fd, long offset, unsigned int size) -{ - char *data; - - data = malloc(size); - if (!data) - return NULL; - lseek(fd, offset, SEEK_SET); - if (read(fd, data, size) != size) { - free(data); - return NULL; - } - return data; -} - -/* load a mach-o object file */ -int load_object(const char *filename, struct target_pt_regs * regs, void ** mh) -{ - int need_bswap = 0; - int entry_point = 0; - int dyld_entry_point = 0; - int slide, mmapfixed; - int fd; - struct load_command *lcmds, *lc; - int is_fat = 0; - unsigned int i, magic; - int mach_hdr_pos = 0; - struct mach_header mach_hdr; - - /* for symbol lookup with -d flag. */ - struct symtab_command * symtabcmd = 0; - struct nlist_extended *symtab, *sym; - struct nlist *symtab_std, *syment; - char *strtab; - - fd = open(filename, O_RDONLY); - if (fd < 0) - qerror("can't open file '%s'", filename); - - /* Read magic header. */ - if (read(fd, &magic, sizeof (magic)) != sizeof (magic)) - qerror("unable to read Magic of '%s'", filename); - - /* Check Mach identification. */ - if(magic == MH_MAGIC) - { - is_fat = 0; - need_bswap = 0; - } else if (magic == MH_CIGAM) - { - is_fat = 0; - need_bswap = 1; - } else if (magic == FAT_MAGIC) - { - is_fat = 1; - need_bswap = 0; - } else if (magic == FAT_CIGAM) - { - is_fat = 1; - need_bswap = 1; - } - else - qerror("Not a Mach-O file.", filename); - - DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]"); - if(is_fat) - { - int found = 0; - struct fat_header fh; - struct fat_arch *fa; - - lseek(fd, 0, SEEK_SET); - - /* Read Fat header. */ - if (read(fd, &fh, sizeof (fh)) != sizeof (fh)) - qerror("unable to read file header"); - - if(need_bswap) - bswap_fh(&fh); - - /* Read Fat Arch. */ - fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch); - - if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch) - qerror("unable to read file header"); - - for( i = 0; i < fh.nfat_arch; i++, fa++) - { - if(need_bswap) - bswap_fa(fa); - if(fa->cputype == TARGET_CPU_TYPE) - { - mach_hdr_pos = fa->offset; - lseek(fd, mach_hdr_pos, SEEK_SET); - - /* Read Mach header. */ - - if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header)) - qerror("unable to read file header"); - - if(mach_hdr.magic == MH_MAGIC) - need_bswap = 0; - else if (mach_hdr.magic == MH_CIGAM) - need_bswap = 1; - else - qerror("Invalid mach header in Fat Mach-O File"); - found = 1; - break; - } - } - if(!found) - qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME); - } - else - { - lseek(fd, 0, SEEK_SET); - /* Read Mach header */ - if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr)) - qerror("%s: unable to read file header", filename); - } - - if(need_bswap) - bswap_mh(&mach_hdr); - - if ((mach_hdr.cputype) != TARGET_CPU_TYPE) - qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME); - - - switch(mach_hdr.filetype) - { - case MH_EXECUTE: break; - case MH_FVMLIB: - case MH_DYLIB: - case MH_DYLINKER: break; - default: - qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype); - } - - /* read segment headers */ - lcmds = malloc(mach_hdr.sizeofcmds); - - if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds) - qerror("%s: unable to read load_command", filename); - slide = 0; - mmapfixed = 0; - for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++) - { - - if(need_bswap) - bswap_lc(lc); - switch(lc->cmd) - { - case LC_SEGMENT: - /* The main_exe can't be relocated */ - if(mach_hdr.filetype == MH_EXECUTE) - mmapfixed = 1; - - slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide); - - /* other segment must be mapped according to slide exactly, if load_segment did something */ - if(slide != -1) - mmapfixed = 1; - else - slide = 0; /* load_segment didn't map the segment */ - - if(mach_hdr.filetype == MH_EXECUTE && slide != 0) - qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide); - - if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0) - { - /* Text section */ - if(mach_hdr.filetype == MH_EXECUTE) - { - /* return the mach_header */ - *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide); - } - else - { - /* it is dyld save the section for gdb, we will be interested in dyld symbol - while debuging */ - macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide); - macho_offset = slide; - } - } - break; - case LC_LOAD_DYLINKER: - dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap ); - break; - case LC_LOAD_DYLIB: - /* dyld will do that for us */ - break; - case LC_THREAD: - case LC_UNIXTHREAD: - { - struct target_pt_regs * _regs; - if(mach_hdr.filetype == MH_DYLINKER) - _regs = regs; - else - _regs = 0; - entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap ); - } - break; - case LC_SYMTAB: - /* Save the symtab and strtab */ - symtabcmd = (struct symtab_command *)lc; - break; - case LC_ID_DYLINKER: - case LC_ID_DYLIB: - case LC_UUID: - case LC_DYSYMTAB: - case LC_TWOLEVEL_HINTS: - case LC_PREBIND_CKSUM: - case LC_SUB_LIBRARY: - break; - default: fprintf(stderr, "warning: unknown command 0x%x in '%s'\n", lc->cmd, filename); - } - lc = (struct load_command*)((int)(lc)+(lc->cmdsize)); - } - - if(symtabcmd) - { - if(need_bswap) - bswap_symtabcmd(symtabcmd); - - symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist)); - strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize); - - symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms); - - if(need_bswap) - { - for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++) - bswap_sym(syment); - } - - for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++) - { - struct nlist *sym_follow, *sym_next = 0; - unsigned int j; - memset(sym, 0, sizeof(*sym)); - - sym->n_type = syment->n_type; - if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */ - continue; - - memcpy(sym, syment, sizeof(*syment)); - - /* Find the following symbol in order to get the current symbol size */ - for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) { - if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value)) - continue; - if(!sym_next) { - sym_next = sym_follow; - continue; - } - if(!(sym_next->n_value > sym_follow->n_value)) - continue; - sym_next = sym_follow; - } - if(sym_next) - sym->st_size = sym_next->n_value - sym->st_value; - else - sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */ - - sym->st_value += slide; - } - - free((void*)symtab_std); - - { - DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms); - struct syminfo *s; - s = malloc(sizeof(*s)); - s->disas_symtab = symtab; - s->disas_strtab = strtab; - s->disas_num_syms = symtabcmd->nsyms; - s->next = syminfos; - syminfos = s; - } - } - close(fd); - if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point) - return dyld_entry_point; - else - return entry_point+slide; -} - -extern unsigned long stack_size; - -unsigned long setup_arg_pages(void * mh, char ** argv, char ** env) -{ - unsigned long stack_base, error, size; - int i; - int * stack; - int argc, envc; - - /* Create enough stack to hold everything. If we don't use - * it for args, we'll use it for something else... - */ - size = stack_size; - - error = target_mmap(0, - size + qemu_host_page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); - if (error == -1) - qerror("stk mmap"); - - /* we reserve one extra page at the top of the stack as guard */ - target_mprotect(error + size, qemu_host_page_size, PROT_NONE); - - stack_base = error + size; - stack = (void*)stack_base; -/* - * | STRING AREA | - * +-------------+ - * | 0 | -* +-------------+ - * | apple[n] | - * +-------------+ - * : - * +-------------+ - * | apple[0] | - * +-------------+ - * | 0 | - * +-------------+ - * | env[n] | - * +-------------+ - * : - * : - * +-------------+ - * | env[0] | - * +-------------+ - * | 0 | - * +-------------+ - * | arg[argc-1] | - * +-------------+ - * : - * : - * +-------------+ - * | arg[0] | - * +-------------+ - * | argc | - * +-------------+ - * sp-> | mh | address of where the a.out's file offset 0 is in memory - * +-------------+ -*/ - /* Construct the stack Stack grows down */ - stack--; - - /* XXX: string should go up there */ - - *stack = 0; - stack--; - - /* Push the absolute path of our executable */ - DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]); - stl(stack, (int) argv[0]); - - stack--; - - stl(stack, 0); - stack--; - - /* Get envc */ - for(envc = 0; env[envc]; envc++); - - for(i = envc-1; i >= 0; i--) - { - DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]); - stl(stack, (int)env[i]); - stack--; - - /* XXX: remove that when string will be on top of the stack */ - page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID); - } - - /* Add on the stack the interp_prefix chosen if so */ - if(interp_prefix[0]) - { - char *dyld_root; - asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix); - page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID); - - stl(stack, (int)dyld_root); - stack--; - } - -#ifdef DONT_USE_DYLD_SHARED_MAP - { - char *shared_map_mode; - asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid"); - page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID); - - stl(stack, (int)shared_map_mode); - stack--; - } -#endif - -#ifdef ACTIVATE_DYLD_TRACE - char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes", - "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes", - "DYLD_PRINT_INITIALIZERS=yes", - "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" }; - - char ** extra_env = malloc(sizeof(extra_env_static)); - bcopy(extra_env_static, extra_env, sizeof(extra_env_static)); - page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID); - - for(i = 0; i<9; i++) - { - DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]); - stl(stack, (int) extra_env[i]); - stack--; - } -#endif - - stl(stack, 0); - stack--; - - /* Get argc */ - for(argc = 0; argv[argc]; argc++); - - for(i = argc-1; i >= 0; i--) - { - DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]); - stl(stack, (int) argv[i]); - stack--; - - /* XXX: remove that when string will be on top of the stack */ - page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID); - } - - DPRINTF("pushing argc %d\n", argc); - stl(stack, argc); - stack--; - - DPRINTF("pushing mh 0x%x\n", (int)mh); - stl(stack, (int) mh); - - /* Stack points on the mh */ - return (unsigned long)stack; -} - -int mach_exec(const char * filename, char ** argv, char ** envp, - struct target_pt_regs * regs) -{ - int entrypoint, stack; - void * mh; /* the Mach Header that will be used by dyld */ - - DPRINTF("mach_exec at 0x%x\n", (int)mach_exec); - - entrypoint = load_object(filename, regs, &mh); - stack = setup_arg_pages(mh, argv, envp); -#if defined(TARGET_I386) - regs->eip = entrypoint; - regs->esp = stack; -#elif defined(TARGET_PPC) - regs->nip = entrypoint; - regs->gpr[1] = stack; -#endif - DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh); - - if(!entrypoint) - qerror("%s: no entry point!\n", filename); - - return 0; -} diff --git a/darwin-user/main.c b/darwin-user/main.c deleted file mode 100644 index 544e219cd4..0000000000 --- a/darwin-user/main.c +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * qemu user main - * - * 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, see <http://www.gnu.org/licenses/>. - */ -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> - -#include <sys/syscall.h> -#include <sys/mman.h> - -#include "qemu.h" -#include "qemu-common.h" - -#define DEBUG_LOGFILE "/tmp/qemu.log" - -#ifdef __APPLE__ -#include <crt_externs.h> -# define environ (*_NSGetEnviron()) -#endif - -#include <mach/mach_init.h> -#include <mach/vm_map.h> - -int singlestep; - -const char *interp_prefix = ""; - -asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000"); - -/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so - we allocate a bigger stack. Need a better solution, for example - by remapping the process stack directly at the right place */ -unsigned long stack_size = 512 * 1024; - -void qerror(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); - exit(1); -} - -void gemu_log(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); -} - -int cpu_get_pic_interrupt(CPUArchState *env) -{ - return -1; -} -#ifdef TARGET_PPC - -static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) -{ - /* TO FIX */ - return 0; -} - -uint64_t cpu_ppc_load_tbl(CPUPPCState *env) -{ - return cpu_ppc_get_tb(env); -} - -uint32_t cpu_ppc_load_tbu(CPUPPCState *env) -{ - return cpu_ppc_get_tb(env) >> 32; -} - -uint64_t cpu_ppc_load_atbl(CPUPPCState *env) -{ - return cpu_ppc_get_tb(env); -} - -uint32_t cpu_ppc_load_atbu(CPUPPCState *env) -{ - return cpu_ppc_get_tb(env) >> 32; -} - -uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) -{ - cpu_ppc_load_tbu(env); -} - -uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) -{ - return cpu_ppc_load_tbl(env) & 0x3FFFFF80; -} - -/* XXX: to be fixed */ -int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) -{ - return -1; -} - -int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) -{ - return -1; -} - -#define EXCP_DUMP(env, fmt, ...) \ -do { \ - fprintf(stderr, fmt , ## __VA_ARGS__); \ - cpu_dump_state(env, stderr, fprintf, 0); \ - qemu_log(fmt, ## __VA_ARGS__); \ - log_cpu_state(env, 0); \ -} while (0) - -void cpu_loop(CPUPPCState *env) -{ - int trapnr; - uint32_t ret; - target_siginfo_t info; - - for(;;) { - trapnr = cpu_ppc_exec(env); - switch(trapnr) { - case POWERPC_EXCP_NONE: - /* Just go on */ - break; - case POWERPC_EXCP_CRITICAL: /* Critical input */ - cpu_abort(env, "Critical interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_MCHECK: /* Machine check exception */ - cpu_abort(env, "Machine check exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_DSI: /* Data storage exception */ -#ifndef DAR -/* To deal with multiple qemu header version as host for the darwin-user code */ -# define DAR SPR_DAR -#endif - EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", - env->spr[SPR_DAR]); - /* Handle this via the gdb */ - gdb_handlesig (env, SIGSEGV); - - info.si_addr = (void*)env->nip; - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_ISI: /* Instruction storage exception */ - EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx "\n", - env->spr[SPR_DAR]); - /* Handle this via the gdb */ - gdb_handlesig (env, SIGSEGV); - - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_EXTERNAL: /* External input */ - cpu_abort(env, "External interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_ALIGN: /* Alignment exception */ - EXCP_DUMP(env, "Unaligned memory access\n"); - info.si_errno = 0; - info.si_code = BUS_ADRALN; - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_PROGRAM: /* Program exception */ - /* XXX: check this */ - switch (env->error_code & ~0xF) { - case POWERPC_EXCP_FP: - EXCP_DUMP(env, "Floating point program exception\n"); - /* Set FX */ - info.si_signo = SIGFPE; - info.si_errno = 0; - switch (env->error_code & 0xF) { - case POWERPC_EXCP_FP_OX: - info.si_code = FPE_FLTOVF; - break; - case POWERPC_EXCP_FP_UX: - info.si_code = FPE_FLTUND; - break; - case POWERPC_EXCP_FP_ZX: - case POWERPC_EXCP_FP_VXZDZ: - info.si_code = FPE_FLTDIV; - break; - case POWERPC_EXCP_FP_XX: - info.si_code = FPE_FLTRES; - break; - case POWERPC_EXCP_FP_VXSOFT: - info.si_code = FPE_FLTINV; - break; - case POWERPC_EXCP_FP_VXSNAN: - case POWERPC_EXCP_FP_VXISI: - case POWERPC_EXCP_FP_VXIDI: - case POWERPC_EXCP_FP_VXIMZ: - case POWERPC_EXCP_FP_VXVC: - case POWERPC_EXCP_FP_VXSQRT: - case POWERPC_EXCP_FP_VXCVI: - info.si_code = FPE_FLTSUB; - break; - default: - EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", - env->error_code); - break; - } - break; - case POWERPC_EXCP_INVAL: - EXCP_DUMP(env, "Invalid instruction\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - switch (env->error_code & 0xF) { - case POWERPC_EXCP_INVAL_INVAL: - info.si_code = ILL_ILLOPC; - break; - case POWERPC_EXCP_INVAL_LSWX: - info.si_code = ILL_ILLOPN; - break; - case POWERPC_EXCP_INVAL_SPR: - info.si_code = ILL_PRVREG; - break; - case POWERPC_EXCP_INVAL_FP: - info.si_code = ILL_COPROC; - break; - default: - EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", - env->error_code & 0xF); - info.si_code = ILL_ILLADR; - break; - } - /* Handle this via the gdb */ - gdb_handlesig (env, SIGSEGV); - break; - case POWERPC_EXCP_PRIV: - EXCP_DUMP(env, "Privilege violation\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - switch (env->error_code & 0xF) { - case POWERPC_EXCP_PRIV_OPC: - info.si_code = ILL_PRVOPC; - break; - case POWERPC_EXCP_PRIV_REG: - info.si_code = ILL_PRVREG; - break; - default: - EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", - env->error_code & 0xF); - info.si_code = ILL_PRVOPC; - break; - } - break; - case POWERPC_EXCP_TRAP: - cpu_abort(env, "Tried to call a TRAP\n"); - break; - default: - /* Should not happen ! */ - cpu_abort(env, "Unknown program exception (%02x)\n", - env->error_code); - break; - } - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ - EXCP_DUMP(env, "No floating point allowed\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_COPROC; - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_SYSCALL: /* System call exception */ - cpu_abort(env, "Syscall exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ - EXCP_DUMP(env, "No APU instruction allowed\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_COPROC; - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_DECR: /* Decrementer exception */ - cpu_abort(env, "Decrementer interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ - cpu_abort(env, "Fix interval timer interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ - cpu_abort(env, "Watchdog timer interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_DTLB: /* Data TLB error */ - cpu_abort(env, "Data TLB exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_ITLB: /* Instruction TLB error */ - cpu_abort(env, "Instruction TLB exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_DEBUG: /* Debug interrupt */ - gdb_handlesig (env, SIGTRAP); - break; - case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */ - EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_COPROC; - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */ - cpu_abort(env, "Embedded floating-point data IRQ not handled\n"); - break; - case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */ - cpu_abort(env, "Embedded floating-point round IRQ not handled\n"); - break; - case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */ - cpu_abort(env, "Performance monitor exception not handled\n"); - break; - case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ - cpu_abort(env, "Doorbell interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ - cpu_abort(env, "Doorbell critical interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_RESET: /* System reset exception */ - cpu_abort(env, "Reset interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_DSEG: /* Data segment exception */ - cpu_abort(env, "Data segment exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_ISEG: /* Instruction segment exception */ - cpu_abort(env, "Instruction segment exception " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ - cpu_abort(env, "Hypervisor decrementer interrupt " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_TRACE: /* Trace exception */ - /* Nothing to do: - * we use this exception to emulate step-by-step execution mode. - */ - break; - case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ - cpu_abort(env, "Hypervisor data storage exception " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */ - cpu_abort(env, "Hypervisor instruction storage exception " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ - cpu_abort(env, "Hypervisor data segment exception " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */ - cpu_abort(env, "Hypervisor instruction segment exception " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_VPU: /* Vector unavailable exception */ - EXCP_DUMP(env, "No Altivec instructions allowed\n"); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_COPROC; - info.si_addr = (void*)(env->nip - 4); - queue_signal(info.si_signo, &info); - break; - case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */ - cpu_abort(env, "Programmable interval timer interrupt " - "while in user mode. Aborting\n"); - break; - case POWERPC_EXCP_IO: /* IO error exception */ - cpu_abort(env, "IO error exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_RUNM: /* Run mode exception */ - cpu_abort(env, "Run mode exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_EMUL: /* Emulation trap exception */ - cpu_abort(env, "Emulation trap exception not handled\n"); - break; - case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ - cpu_abort(env, "Instruction fetch TLB exception " - "while in user-mode. Aborting"); - break; - case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ - cpu_abort(env, "Data load TLB exception while in user-mode. " - "Aborting"); - break; - case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ - cpu_abort(env, "Data store TLB exception while in user-mode. " - "Aborting"); - break; - case POWERPC_EXCP_FPA: /* Floating-point assist exception */ - cpu_abort(env, "Floating-point assist exception not handled\n"); - break; - case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ - cpu_abort(env, "Instruction address breakpoint exception " - "not handled\n"); - break; - case POWERPC_EXCP_SMI: /* System management interrupt */ - cpu_abort(env, "System management interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_THERM: /* Thermal interrupt */ - cpu_abort(env, "Thermal interrupt interrupt while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */ - cpu_abort(env, "Performance monitor exception not handled\n"); - break; - case POWERPC_EXCP_VPUA: /* Vector assist exception */ - cpu_abort(env, "Vector assist exception not handled\n"); - break; - case POWERPC_EXCP_SOFTP: /* Soft patch exception */ - cpu_abort(env, "Soft patch exception not handled\n"); - break; - case POWERPC_EXCP_MAINT: /* Maintenance exception */ - cpu_abort(env, "Maintenance exception while in user mode. " - "Aborting\n"); - break; - case POWERPC_EXCP_STOP: /* stop translation */ - /* We did invalidate the instruction cache. Go on */ - break; - case POWERPC_EXCP_BRANCH: /* branch instruction: */ - /* We just stopped because of a branch. Go on */ - break; - case POWERPC_EXCP_SYSCALL_USER: - /* system call in user-mode emulation */ - /* system call */ - if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0) - ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4], - env->gpr[5], env->gpr[6], env->gpr[7], - env->gpr[8], env->gpr[9], env->gpr[10]*/); - else if(((int)env->gpr[0])<0) - ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], - env->gpr[5], env->gpr[6], env->gpr[7], - env->gpr[8], env->gpr[9], env->gpr[10]); - else - ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], - env->gpr[5], env->gpr[6], env->gpr[7], - env->gpr[8], env->gpr[9], env->gpr[10]); - - /* Unix syscall error signaling */ - if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0) - { - if( (int)ret < 0 ) - env->nip += 0; - else - env->nip += 4; - } - - /* Return value */ - env->gpr[3] = ret; - break; - case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; - default: - cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr); - break; - } - process_pending_signals(env); - } -} -#endif - - -#ifdef TARGET_I386 - -/***********************************************************/ -/* CPUX86 core interface */ - -uint64_t cpu_get_tsc(CPUX86State *env) -{ - return cpu_get_real_ticks(); -} - -void -write_dt(void *ptr, unsigned long addr, unsigned long limit, - int flags) -{ - unsigned int e1, e2; - e1 = (addr << 16) | (limit & 0xffff); - e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); - e2 |= flags; - stl((uint8_t *)ptr, e1); - stl((uint8_t *)ptr + 4, e2); -} - -static void set_gate(void *ptr, unsigned int type, unsigned int dpl, - unsigned long addr, unsigned int sel) -{ - unsigned int e1, e2; - e1 = (addr & 0xffff) | (sel << 16); - e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); - stl((uint8_t *)ptr, e1); - stl((uint8_t *)ptr + 4, e2); -} - -#define GDT_TABLE_SIZE 14 -#define LDT_TABLE_SIZE 15 -#define IDT_TABLE_SIZE 256 -#define TSS_SIZE 104 -uint64_t gdt_table[GDT_TABLE_SIZE]; -uint64_t ldt_table[LDT_TABLE_SIZE]; -uint64_t idt_table[IDT_TABLE_SIZE]; -uint32_t tss[TSS_SIZE]; - -/* only dpl matters as we do only user space emulation */ -static void set_idt(int n, unsigned int dpl) -{ - set_gate(idt_table + n, 0, dpl, 0, 0); -} - -/* ABI convention: after a syscall if there was an error the CF flag is set */ -static inline void set_error(CPUX86State *env, int ret) -{ - if(ret<0) - env->eflags = env->eflags | 0x1; - else - env->eflags &= ~0x1; - env->regs[R_EAX] = ret; -} - -void cpu_loop(CPUX86State *env) -{ - int trapnr; - int ret; - uint8_t *pc; - target_siginfo_t info; - - for(;;) { - trapnr = cpu_x86_exec(env); - uint32_t *params = (uint32_t *)env->regs[R_ESP]; - switch(trapnr) { - case 0x79: /* Our commpage hack back door exit is here */ - do_commpage(env, env->eip, *(params + 1), *(params + 2), - *(params + 3), *(params + 4), - *(params + 5), *(params + 6), - *(params + 7), *(params + 8)); - break; - case 0x81: /* mach syscall */ - { - ret = do_mach_syscall(env, env->regs[R_EAX], - *(params + 1), *(params + 2), - *(params + 3), *(params + 4), - *(params + 5), *(params + 6), - *(params + 7), *(params + 8)); - set_error(env, ret); - break; - } - case 0x90: /* unix backdoor */ - { - /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/ - int saved_stack = env->regs[R_ESP]; - env->regs[R_ESP] = env->regs[R_ECX]; - - ret = do_unix_syscall(env, env->regs[R_EAX]); - - env->regs[R_ECX] = env->regs[R_ESP]; - env->regs[R_ESP] = saved_stack; - - set_error(env, ret); - break; - } - case 0x80: /* unix syscall */ - { - ret = do_unix_syscall(env, env->regs[R_EAX]/*, - *(params + 1), *(params + 2), - *(params + 3), *(params + 4), - *(params + 5), *(params + 6), - *(params + 7), *(params + 8)*/); - set_error(env, ret); - break; - } - case 0x82: /* thread syscall */ - { - ret = do_thread_syscall(env, env->regs[R_EAX], - *(params + 1), *(params + 2), - *(params + 3), *(params + 4), - *(params + 5), *(params + 6), - *(params + 7), *(params + 8)); - set_error(env, ret); - break; - } - case EXCP0B_NOSEG: - case EXCP0C_STACK: - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_NOOP; - info.si_addr = 0; - gdb_handlesig (env, SIGBUS); - queue_signal(info.si_signo, &info); - break; - case EXCP0D_GPF: - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_NOOP; - info.si_addr = 0; - gdb_handlesig (env, SIGSEGV); - queue_signal(info.si_signo, &info); - break; - case EXCP0E_PAGE: - info.si_signo = SIGSEGV; - info.si_errno = 0; - if (!(env->error_code & 1)) - info.si_code = SEGV_MAPERR; - else - info.si_code = SEGV_ACCERR; - info.si_addr = (void*)env->cr[2]; - gdb_handlesig (env, SIGSEGV); - queue_signal(info.si_signo, &info); - break; - case EXCP00_DIVZ: - /* division by zero */ - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_code = FPE_INTDIV; - info.si_addr = (void*)env->eip; - gdb_handlesig (env, SIGFPE); - queue_signal(info.si_signo, &info); - break; - case EXCP01_SSTP: - case EXCP03_INT3: - info.si_signo = SIGTRAP; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - info.si_addr = (void*)env->eip; - gdb_handlesig (env, SIGTRAP); - queue_signal(info.si_signo, &info); - break; - case EXCP04_INTO: - case EXCP05_BOUND: - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = SEGV_NOOP; - info.si_addr = 0; - gdb_handlesig (env, SIGSEGV); - queue_signal(info.si_signo, &info); - break; - case EXCP06_ILLOP: - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_ILLOPN; - info.si_addr = (void*)env->eip; - gdb_handlesig (env, SIGILL); - queue_signal(info.si_signo, &info); - break; - case EXCP_INTERRUPT: - /* just indicate that signals should be handled asap */ - break; - case EXCP_DEBUG: - { - int sig; - - sig = gdb_handlesig (env, SIGTRAP); - if (sig) - { - info.si_signo = sig; - info.si_errno = 0; - info.si_code = TRAP_BRKPT; - queue_signal(info.si_signo, &info); - } - } - break; - default: - pc = (void*)(env->segs[R_CS].base + env->eip); - fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", - (long)pc, trapnr); - abort(); - } - process_pending_signals(env); - } -} -#endif - -static void usage(void) -{ - printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n" - "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n" - "Darwin CPU emulator (compiled for %s emulation)\n" - "\n" - "-h print this help\n" - "-L path set the %s library path (default='%s')\n" - "-s size set the stack size in bytes (default=%ld)\n" - "\n" - "debug options:\n" - "-d options activate log (logfile='%s')\n" - "-g wait for gdb on port 1234\n" - "-p pagesize set the host page size to 'pagesize'\n", - "-singlestep always run in singlestep mode\n" - TARGET_ARCH, - TARGET_ARCH, - interp_prefix, - stack_size, - DEBUG_LOGFILE); - exit(1); -} - -/* XXX: currently only used for async signals (see signal.c) */ -CPUArchState *global_env; - -/* used to free thread contexts */ -TaskState *first_task_state; - -int main(int argc, char **argv) -{ - const char *filename; - const char *log_file = DEBUG_LOGFILE; - const char *log_mask = NULL; - struct target_pt_regs regs1, *regs = ®s1; - TaskState ts1, *ts = &ts1; - CPUArchState *env; - int optind; - short use_gdbstub = 0; - const char *r; - const char *cpu_model; - - if (argc <= 1) - usage(); - - module_call_init(MODULE_INIT_QOM); - - optind = 1; - for(;;) { - if (optind >= argc) - break; - r = argv[optind]; - if (r[0] != '-') - break; - optind++; - r++; - if (!strcmp(r, "-")) { - break; - } else if (!strcmp(r, "d")) { - if (optind >= argc) { - break; - } - log_mask = argv[optind++]; - } else if (!strcmp(r, "D")) { - if (optind >= argc) { - break; - } - log_file = argv[optind++]; - } else if (!strcmp(r, "s")) { - r = argv[optind++]; - stack_size = strtol(r, (char **)&r, 0); - if (stack_size <= 0) - usage(); - if (*r == 'M') - stack_size *= 1024 * 1024; - else if (*r == 'k' || *r == 'K') - stack_size *= 1024; - } else if (!strcmp(r, "L")) { - interp_prefix = argv[optind++]; - } else if (!strcmp(r, "p")) { - qemu_host_page_size = atoi(argv[optind++]); - if (qemu_host_page_size == 0 || - (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { - fprintf(stderr, "page size must be a power of two\n"); - exit(1); - } - } else - if (!strcmp(r, "g")) { - use_gdbstub = 1; - } else if (!strcmp(r, "cpu")) { - cpu_model = argv[optind++]; - if (strcmp(cpu_model, "?") == 0) { -/* XXX: implement xxx_cpu_list for targets that still miss it */ -#if defined(cpu_list) - cpu_list(stdout, &fprintf); -#endif - exit(1); - } - } else if (!strcmp(r, "singlestep")) { - singlestep = 1; - } else - { - usage(); - } - } - - /* init debug */ - cpu_set_log_filename(log_file); - if (log_mask) { - int mask; - CPULogItem *item; - - mask = cpu_str_to_log_mask(log_mask); - if (!mask) { - printf("Log items (comma separated):\n"); - for (item = cpu_log_items; item->mask != 0; item++) { - printf("%-10s %s\n", item->name, item->help); - } - exit(1); - } - cpu_set_log(mask); - } - - if (optind >= argc) { - usage(); - } - filename = argv[optind]; - - /* Zero out regs */ - memset(regs, 0, sizeof(struct target_pt_regs)); - - if (cpu_model == NULL) { -#if defined(TARGET_I386) -#ifdef TARGET_X86_64 - cpu_model = "qemu64"; -#else - cpu_model = "qemu32"; -#endif -#elif defined(TARGET_PPC) -#ifdef TARGET_PPC64 - cpu_model = "970"; -#else - cpu_model = "750"; -#endif -#else -#error unsupported CPU -#endif - } - tcg_exec_init(0); - cpu_exec_init_all(); - /* NOTE: we need to init the CPU at this stage to get - qemu_host_page_size */ - env = cpu_init(cpu_model); - cpu_state_reset(env); - - printf("Starting %s with qemu\n----------------\n", filename); - - commpage_init(); - - if (mach_exec(filename, argv+optind, environ, regs) != 0) { - printf("Error loading %s\n", filename); - _exit(1); - } - - syscall_init(); - signal_init(); - global_env = env; - - /* build Task State */ - memset(ts, 0, sizeof(TaskState)); - env->opaque = ts; - ts->used = 1; - -#if defined(TARGET_I386) - cpu_x86_set_cpl(env, 3); - - env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; - env->hflags |= HF_PE_MASK; - - if (env->cpuid_features & CPUID_SSE) { - env->cr[4] |= CR4_OSFXSR_MASK; - env->hflags |= HF_OSFXSR_MASK; - } - - /* flags setup : we activate the IRQs by default as in user mode */ - env->eflags |= IF_MASK; - - /* darwin register setup */ - env->regs[R_EAX] = regs->eax; - env->regs[R_EBX] = regs->ebx; - env->regs[R_ECX] = regs->ecx; - env->regs[R_EDX] = regs->edx; - env->regs[R_ESI] = regs->esi; - env->regs[R_EDI] = regs->edi; - env->regs[R_EBP] = regs->ebp; - env->regs[R_ESP] = regs->esp; - env->eip = regs->eip; - - /* Darwin LDT setup */ - /* 2 - User code segment - 3 - User data segment - 4 - User cthread */ - bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0])); - env->ldt.base = (uint32_t) ldt_table; - env->ldt.limit = sizeof(ldt_table) - 1; - - write_dt(ldt_table + 2, 0, 0xfffff, - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | - (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); - write_dt(ldt_table + 3, 0, 0xfffff, - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | - (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); - write_dt(ldt_table + 4, 0, 0xfffff, - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | - (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); - - /* Darwin GDT setup. - * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86, - now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */ - bzero(gdt_table, sizeof(gdt_table)); - env->gdt.base = (uint32_t)gdt_table; - env->gdt.limit = sizeof(gdt_table) - 1; - - /* Set up a back door to handle sysenter syscalls (unix) */ - char * syscallbackdoor = malloc(64); - page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID); - - int i = 0; - syscallbackdoor[i++] = 0xcd; - syscallbackdoor[i++] = 0x90; /* int 0x90 */ - syscallbackdoor[i++] = 0x0F; - syscallbackdoor[i++] = 0x35; /* sysexit */ - - /* Darwin sysenter/sysexit setup */ - env->sysenter_cs = 0x1; //XXX - env->sysenter_eip = (int)syscallbackdoor; - env->sysenter_esp = (int)malloc(64); - - /* Darwin TSS setup - This must match up with GDT[4] */ - env->tr.base = (uint32_t) tss; - env->tr.limit = sizeof(tss) - 1; - env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT); - stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment - - /* Darwin interrupt setup */ - bzero(idt_table, sizeof(idt_table)); - env->idt.base = (uint32_t) idt_table; - env->idt.limit = sizeof(idt_table) - 1; - set_idt(0, 0); - set_idt(1, 0); - set_idt(2, 0); - set_idt(3, 3); - set_idt(4, 3); - set_idt(5, 3); - set_idt(6, 0); - set_idt(7, 0); - set_idt(8, 0); - set_idt(9, 0); - set_idt(10, 0); - set_idt(11, 0); - set_idt(12, 0); - set_idt(13, 0); - set_idt(14, 0); - set_idt(15, 0); - set_idt(16, 0); - set_idt(17, 0); - set_idt(18, 0); - set_idt(19, 0); - /* Syscalls are done via - int 0x80 (unix) (rarely used) - int 0x81 (mach) - int 0x82 (thread) - int 0x83 (diag) (not handled here) - sysenter/sysexit (unix) -> we redirect that to int 0x90 */ - set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */ - set_idt(0x80, 3); /* Unix Syscall */ - set_idt(0x81, 3); /* Mach Syscalls */ - set_idt(0x82, 3); /* thread Syscalls */ - - set_idt(0x90, 3); /* qemu-darwin-user's Unix syscalls backdoor */ - - - cpu_x86_load_seg(env, R_CS, __USER_CS); - cpu_x86_load_seg(env, R_DS, __USER_DS); - cpu_x86_load_seg(env, R_ES, __USER_DS); - cpu_x86_load_seg(env, R_SS, __USER_DS); - cpu_x86_load_seg(env, R_FS, __USER_DS); - cpu_x86_load_seg(env, R_GS, __USER_DS); - -#elif defined(TARGET_PPC) - { - int i; - -#if defined(TARGET_PPC64) -#if defined(TARGET_ABI32) - env->msr &= ~((target_ulong)1 << MSR_SF); -#else - env->msr |= (target_ulong)1 << MSR_SF; -#endif -#endif - env->nip = regs->nip; - for(i = 0; i < 32; i++) { - env->gpr[i] = regs->gpr[i]; - } - } -#else -#error unsupported target CPU -#endif - - if (use_gdbstub) { - printf("Waiting for gdb Connection on port 1234...\n"); - gdbserver_start (1234); - gdb_handlesig(env, 0); - } - - cpu_loop(env); - /* never exits */ - return 0; -} diff --git a/darwin-user/mmap.c b/darwin-user/mmap.c deleted file mode 100644 index d840b28d38..0000000000 --- a/darwin-user/mmap.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * mmap support for qemu - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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, see <http://www.gnu.org/licenses/>. - */ -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> -#include <sys/mman.h> - -#include "qemu.h" - -//#define DEBUG_MMAP - -/* NOTE: all the constants are the HOST ones */ -int target_mprotect(unsigned long start, unsigned long len, int prot) -{ - unsigned long end, host_start, host_end, addr; - int prot1, ret; - -#ifdef DEBUG_MMAP - printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len, - prot & PROT_READ ? 'r' : '-', - prot & PROT_WRITE ? 'w' : '-', - prot & PROT_EXEC ? 'x' : '-'); -#endif - - if ((start & ~TARGET_PAGE_MASK) != 0) - return -EINVAL; - len = TARGET_PAGE_ALIGN(len); - end = start + len; - if (end < start) - return -EINVAL; - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) - return -EINVAL; - if (len == 0) - return 0; - - host_start = start & qemu_host_page_mask; - host_end = HOST_PAGE_ALIGN(end); - if (start > host_start) { - /* handle host page containing start */ - prot1 = prot; - for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { - prot1 |= page_get_flags(addr); - } - if (host_end == host_start + qemu_host_page_size) { - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { - prot1 |= page_get_flags(addr); - } - end = host_end; - } - ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS); - if (ret != 0) - return ret; - host_start += qemu_host_page_size; - } - if (end < host_end) { - prot1 = prot; - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { - prot1 |= page_get_flags(addr); - } - ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size, - prot1 & PAGE_BITS); - if (ret != 0) - return ret; - host_end -= qemu_host_page_size; - } - - /* handle the pages in the middle */ - if (host_start < host_end) { - ret = mprotect((void *)host_start, host_end - host_start, prot); - if (ret != 0) - return ret; - } - page_set_flags(start, start + len, prot | PAGE_VALID); - return 0; -} - -/* map an incomplete host page */ -int mmap_frag(unsigned long host_start, - unsigned long start, unsigned long end, - int prot, int flags, int fd, unsigned long offset) -{ - unsigned long host_end, ret, addr; - int prot1, prot_new; - - host_end = host_start + qemu_host_page_size; - - /* get the protection of the target pages outside the mapping */ - prot1 = 0; - for(addr = host_start; addr < host_end; addr++) { - if (addr < start || addr >= end) - prot1 |= page_get_flags(addr); - } - - if (prot1 == 0) { - /* no page was there, so we allocate one */ - ret = (long)mmap((void *)host_start, qemu_host_page_size, prot, - flags | MAP_ANONYMOUS, -1, 0); - if (ret == -1) - return ret; - } - prot1 &= PAGE_BITS; - - prot_new = prot | prot1; - if (!(flags & MAP_ANONYMOUS)) { - /* msync() won't work here, so we return an error if write is - possible while it is a shared mapping */ -#ifndef __APPLE__ - if ((flags & MAP_TYPE) == MAP_SHARED && -#else - if ((flags & MAP_SHARED) && -#endif - (prot & PROT_WRITE)) - return -1; - - /* adjust protection to be able to read */ - if (!(prot1 & PROT_WRITE)) - mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE); - - /* read the corresponding file data */ - pread(fd, (void *)start, end - start, offset); - - /* put final protection */ - if (prot_new != (prot1 | PROT_WRITE)) - mprotect((void *)host_start, qemu_host_page_size, prot_new); - } else { - /* just update the protection */ - if (prot_new != prot1) { - mprotect((void *)host_start, qemu_host_page_size, prot_new); - } - } - return 0; -} - -/* NOTE: all the constants are the HOST ones */ -long target_mmap(unsigned long start, unsigned long len, int prot, - int flags, int fd, unsigned long offset) -{ - unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len; -#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) - static unsigned long last_start = 0x40000000; -#endif - -#ifdef DEBUG_MMAP - { - printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=", - start, len, - prot & PROT_READ ? 'r' : '-', - prot & PROT_WRITE ? 'w' : '-', - prot & PROT_EXEC ? 'x' : '-'); - if (flags & MAP_FIXED) - printf("MAP_FIXED "); - if (flags & MAP_ANONYMOUS) - printf("MAP_ANON "); -#ifndef MAP_TYPE -# define MAP_TYPE 0x3 -#endif - switch(flags & MAP_TYPE) { - case MAP_PRIVATE: - printf("MAP_PRIVATE "); - break; - case MAP_SHARED: - printf("MAP_SHARED "); - break; - default: - printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE); - break; - } - printf("fd=%d offset=%lx\n", fd, offset); - } -#endif - - if (offset & ~TARGET_PAGE_MASK) - return -EINVAL; - - len = TARGET_PAGE_ALIGN(len); - if (len == 0) - return start; - host_start = start & qemu_host_page_mask; - - if (!(flags & MAP_FIXED)) { -#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) - /* tell the kernel to search at the same place as i386 */ - if (host_start == 0) { - host_start = last_start; - last_start += HOST_PAGE_ALIGN(len); - } -#endif - if (qemu_host_page_size != qemu_real_host_page_size) { - /* NOTE: this code is only for debugging with '-p' option */ - /* reserve a memory area */ - host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE; - host_start = (long)mmap((void *)host_start, host_len, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (host_start == -1) - return host_start; - host_end = host_start + host_len; - start = HOST_PAGE_ALIGN(host_start); - end = start + HOST_PAGE_ALIGN(len); - if (start > host_start) - munmap((void *)host_start, start - host_start); - if (end < host_end) - munmap((void *)end, host_end - end); - /* use it as a fixed mapping */ - flags |= MAP_FIXED; - } else { - /* if not fixed, no need to do anything */ - host_offset = offset & qemu_host_page_mask; - host_len = len + offset - host_offset; - start = (long)mmap((void *)host_start, host_len, - prot, flags, fd, host_offset); - if (start == -1) - return start; - /* update start so that it points to the file position at 'offset' */ - if (!(flags & MAP_ANONYMOUS)) - start += offset - host_offset; - goto the_end1; - } - } - - if (start & ~TARGET_PAGE_MASK) - return -EINVAL; - end = start + len; - host_end = HOST_PAGE_ALIGN(end); - - /* worst case: we cannot map the file because the offset is not - aligned, so we read it */ - if (!(flags & MAP_ANONYMOUS) && - (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) { - /* msync() won't work here, so we return an error if write is - possible while it is a shared mapping */ -#ifndef __APPLE__ - if ((flags & MAP_TYPE) == MAP_SHARED && -#else - if ((flags & MAP_SHARED) && -#endif - (prot & PROT_WRITE)) - return -EINVAL; - retaddr = target_mmap(start, len, prot | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); - if (retaddr == -1) - return retaddr; - pread(fd, (void *)start, len, offset); - if (!(prot & PROT_WRITE)) { - ret = target_mprotect(start, len, prot); - if (ret != 0) - return ret; - } - goto the_end; - } - - /* handle the start of the mapping */ - if (start > host_start) { - if (host_end == host_start + qemu_host_page_size) { - /* one single host page */ - ret = mmap_frag(host_start, start, end, - prot, flags, fd, offset); - if (ret == -1) - return ret; - goto the_end1; - } - ret = mmap_frag(host_start, start, host_start + qemu_host_page_size, - prot, flags, fd, offset); - if (ret == -1) - return ret; - host_start += qemu_host_page_size; - } - /* handle the end of the mapping */ - if (end < host_end) { - ret = mmap_frag(host_end - qemu_host_page_size, - host_end - qemu_host_page_size, host_end, - prot, flags, fd, - offset + host_end - qemu_host_page_size - start); - if (ret == -1) - return ret; - host_end -= qemu_host_page_size; - } - - /* map the middle (easier) */ - if (host_start < host_end) { - unsigned long offset1; - if (flags & MAP_ANONYMOUS) - offset1 = 0; - else - offset1 = offset + host_start - start; - ret = (long)mmap((void *)host_start, host_end - host_start, - prot, flags, fd, offset1); - if (ret == -1) - return ret; - } - the_end1: - page_set_flags(start, start + len, prot | PAGE_VALID); - the_end: -#ifdef DEBUG_MMAP - printf("target_mmap: ret=0x%lx\n", (long)start); - page_dump(stdout); - printf("\n"); -#endif - return start; -} - -int target_munmap(unsigned long start, unsigned long len) -{ - unsigned long end, host_start, host_end, addr; - int prot, ret; - -#ifdef DEBUG_MMAP - printf("munmap: start=0x%lx len=0x%lx\n", start, len); -#endif - if (start & ~TARGET_PAGE_MASK) - return -EINVAL; - len = TARGET_PAGE_ALIGN(len); - if (len == 0) - return -EINVAL; - end = start + len; - host_start = start & qemu_host_page_mask; - host_end = HOST_PAGE_ALIGN(end); - - if (start > host_start) { - /* handle host page containing start */ - prot = 0; - for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { - prot |= page_get_flags(addr); - } - if (host_end == host_start + qemu_host_page_size) { - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { - prot |= page_get_flags(addr); - } - end = host_end; - } - if (prot != 0) - host_start += qemu_host_page_size; - } - if (end < host_end) { - prot = 0; - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { - prot |= page_get_flags(addr); - } - if (prot != 0) - host_end -= qemu_host_page_size; - } - - /* unmap what we can */ - if (host_start < host_end) { - ret = munmap((void *)host_start, host_end - host_start); - if (ret != 0) - return ret; - } - - page_set_flags(start, start + len, 0); - return 0; -} - -/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED - blocks which have been allocated starting on a host page */ -long target_mremap(unsigned long old_addr, unsigned long old_size, - unsigned long new_size, unsigned long flags, - unsigned long new_addr) -{ -#ifndef __APPLE__ - /* XXX: use 5 args syscall */ - new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags); - if (new_addr == -1) - return new_addr; - prot = page_get_flags(old_addr); - page_set_flags(old_addr, old_addr + old_size, 0); - page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID); - return new_addr; -#else - qerror("target_mremap: unsupported\n"); -#endif - -} - -int target_msync(unsigned long start, unsigned long len, int flags) -{ - unsigned long end; - - if (start & ~TARGET_PAGE_MASK) - return -EINVAL; - len = TARGET_PAGE_ALIGN(len); - end = start + len; - if (end < start) - return -EINVAL; - if (end == start) - return 0; - - start &= qemu_host_page_mask; - return msync((void *)start, end - start, flags); -} diff --git a/darwin-user/qemu.h b/darwin-user/qemu.h deleted file mode 100644 index 9e16c8e7ba..0000000000 --- a/darwin-user/qemu.h +++ /dev/null @@ -1,178 +0,0 @@ -#ifndef GEMU_H -#define GEMU_H - -#include <signal.h> -#include <string.h> - -#include "cpu.h" - -#include "thunk.h" - -#include "gdbstub.h" - -typedef siginfo_t target_siginfo_t; -#define target_sigaction sigaction -#ifdef TARGET_I386 -struct target_pt_regs { - long ebx; - long ecx; - long edx; - long esi; - long edi; - long ebp; - long eax; - int xds; - int xes; - long orig_eax; - long eip; - int xcs; - long eflags; - long esp; - int xss; -}; -struct target_sigcontext { - int sc_onstack; - int sc_mask; - int sc_eax; - int sc_ebx; - int sc_ecx; - int sc_edx; - int sc_edi; - int sc_esi; - int sc_ebp; - int sc_esp; - int sc_ss; - int sc_eflags; - int sc_eip; - int sc_cs; - int sc_ds; - int sc_es; - int sc_fs; - int sc_gs; -}; - -#define __USER_CS (0x17) -#define __USER_DS (0x1F) - -#elif defined(TARGET_PPC) -struct target_pt_regs { - unsigned long gpr[32]; - unsigned long nip; - unsigned long msr; - unsigned long orig_gpr3; /* Used for restarting system calls */ - unsigned long ctr; - unsigned long link; - unsigned long xer; - unsigned long ccr; - unsigned long mq; /* 601 only (not used at present) */ - /* Used on APUS to hold IPL value. */ - unsigned long trap; /* Reason for being here */ - unsigned long dar; /* Fault registers */ - unsigned long dsisr; - unsigned long result; /* Result of a system call */ -}; - -struct target_sigcontext { - int sc_onstack; /* sigstack state to restore */ - int sc_mask; /* signal mask to restore */ - int sc_ir; /* pc */ - int sc_psw; /* processor status word */ - int sc_sp; /* stack pointer if sc_regs == NULL */ - void *sc_regs; /* (kernel private) saved state */ -}; - -#endif - -typedef struct TaskState { - struct TaskState *next; - int used; /* non zero if used */ - uint8_t stack[0]; -} __attribute__((aligned(16))) TaskState; - -void syscall_init(void); -long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8); -long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8); -long do_unix_syscall(void *cpu_env, int num); -int do_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact); -int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss); - -void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -void qerror(const char *fmt, ...) GCC_FMT_ATTR(1, 2); - -void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags); - -extern CPUArchState *global_env; -void cpu_loop(CPUArchState *env); -void init_paths(const char *prefix); -const char *path(const char *pathname); - -#include "qemu-log.h" - -/* commpage.c */ -void commpage_init(void); -void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8); - -/* signal.c */ -void process_pending_signals(void *cpu_env); -void signal_init(void); -int queue_signal(int sig, target_siginfo_t *info); -void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); -void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); -long do_sigreturn(CPUArchState *env, int num); - -/* machload.c */ -int mach_exec(const char * filename, char ** argv, char ** envp, - struct target_pt_regs * regs); - -/* mmap.c */ -int target_mprotect(unsigned long start, unsigned long len, int prot); -long target_mmap(unsigned long start, unsigned long len, int prot, - int flags, int fd, unsigned long offset); -int target_munmap(unsigned long start, unsigned long len); -long target_mremap(unsigned long old_addr, unsigned long old_size, - unsigned long new_size, unsigned long flags, - unsigned long new_addr); -int target_msync(unsigned long start, unsigned long len, int flags); - -/* user access */ - -/* XXX: todo protect every memory access */ -#define lock_user(x,y,z) (void*)(x) -#define unlock_user(x,y,z) - -/* Mac OS X ABI arguments processing */ -#ifdef TARGET_I386 -static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env) -{ - uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i); - *i+=4; - return tswap32(*args); -} -static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env) -{ - uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i); - *i+=8; - return tswap64(*args); -} -#elif defined(TARGET_PPC) -static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env) -{ - /* XXX: won't work when args goes on stack after gpr10 */ - uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]); - *i+=4; - return tswap32(args); -} -static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env) -{ - /* XXX: won't work when args goes on stack after gpr10 */ - uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]); - *i+=(8 << 8) + 8; - return tswap64(args); -} -#endif - -#endif diff --git a/darwin-user/signal.c b/darwin-user/signal.c deleted file mode 100644 index 489cb64282..0000000000 --- a/darwin-user/signal.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Emulation of Linux signals - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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, see <http://www.gnu.org/licenses/>. - */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <unistd.h> -#include <errno.h> -#include <sys/ucontext.h> - -#ifdef __ia64__ -#undef uc_mcontext -#undef uc_sigmask -#undef uc_stack -#undef uc_link -#endif - -#include "qemu.h" -#include "qemu-common.h" - -#define DEBUG_SIGNAL - -#define MAX_SIGQUEUE_SIZE 1024 - -struct sigqueue { - struct sigqueue *next; - target_siginfo_t info; -}; - -struct emulated_sigaction { - struct target_sigaction sa; - int pending; /* true if signal is pending */ - struct sigqueue *first; - struct sigqueue info; /* in order to always have memory for the - first signal, we put it here */ -}; - -static struct sigaltstack target_sigaltstack_used = { - 0, 0, SA_DISABLE -}; - -static struct emulated_sigaction sigact_table[NSIG]; -static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ -static struct sigqueue *first_free; /* first free siginfo queue entry */ -static int signal_pending; /* non zero if a signal may be pending */ - -static void host_signal_handler(int host_signum, siginfo_t *info, - void *puc); - - -static inline int host_to_target_signal(int sig) -{ - return sig; -} - -static inline int target_to_host_signal(int sig) -{ - return sig; -} - -/* siginfo conversion */ - - - -void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) -{ - -} - -void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) -{ - -} - -void signal_init(void) -{ - struct sigaction act; - int i; - - /* set all host signal handlers. ALL signals are blocked during - the handlers to serialize them. */ - sigfillset(&act.sa_mask); - act.sa_flags = SA_SIGINFO; - act.sa_sigaction = host_signal_handler; - for(i = 1; i < NSIG; i++) { - sigaction(i, &act, NULL); - } - - memset(sigact_table, 0, sizeof(sigact_table)); - - first_free = &sigqueue_table[0]; - for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) - sigqueue_table[i].next = &sigqueue_table[i + 1]; - sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL; -} - -/* signal queue handling */ - -static inline struct sigqueue *alloc_sigqueue(void) -{ - struct sigqueue *q = first_free; - if (!q) - return NULL; - first_free = q->next; - return q; -} - -static inline void free_sigqueue(struct sigqueue *q) -{ - q->next = first_free; - first_free = q; -} - -/* abort execution with signal */ -void QEMU_NORETURN force_sig(int sig) -{ - int host_sig; - host_sig = target_to_host_signal(sig); - fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n", - sig, strsignal(host_sig)); - _exit(-host_sig); -} - -/* queue a signal so that it will be send to the virtual CPU as soon - as possible */ -int queue_signal(int sig, target_siginfo_t *info) -{ - struct emulated_sigaction *k; - struct sigqueue *q, **pq; - target_ulong handler; - -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "queue_signal: sig=%d\n", - sig); -#endif - k = &sigact_table[sig - 1]; - handler = (target_ulong)k->sa.sa_handler; - if (handler == SIG_DFL) { - /* default handler : ignore some signal. The other are fatal */ - if (sig != SIGCHLD && - sig != SIGURG && - sig != SIGWINCH) { - force_sig(sig); - } else { - return 0; /* indicate ignored */ - } - } else if (handler == host_to_target_signal(SIG_IGN)) { - /* ignore signal */ - return 0; - } else if (handler == host_to_target_signal(SIG_ERR)) { - force_sig(sig); - } else { - pq = &k->first; - if (!k->pending) { - /* first signal */ - q = &k->info; - } else { - q = alloc_sigqueue(); - if (!q) - return -EAGAIN; - while (*pq != NULL) - pq = &(*pq)->next; - } - *pq = q; - q->info = *info; - q->next = NULL; - k->pending = 1; - /* signal that a new signal is pending */ - signal_pending = 1; - return 1; /* indicates that the signal was queued */ - } -} - -static void host_signal_handler(int host_signum, siginfo_t *info, - void *puc) -{ - int sig; - target_siginfo_t tinfo; - - /* the CPU emulator uses some host signals to detect exceptions, - we we forward to it some signals */ - if (host_signum == SIGSEGV || host_signum == SIGBUS) { - if (cpu_signal_handler(host_signum, (void*)info, puc)) - return; - } - - /* get target signal number */ - sig = host_to_target_signal(host_signum); - if (sig < 1 || sig > NSIG) - return; - -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "qemu: got signal %d\n", sig); -#endif - if (queue_signal(sig, &tinfo) == 1) { - /* interrupt the virtual CPU as soon as possible */ - cpu_exit(global_env); - } -} - -int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss) -{ - /* XXX: test errors */ - if(oss) - { - oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp); - oss->ss_size = tswap32(target_sigaltstack_used.ss_size); - oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags); - } - if(ss) - { - target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp); - target_sigaltstack_used.ss_size = tswap32(ss->ss_size); - target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags); - } - return 0; -} - -int do_sigaction(int sig, const struct sigaction *act, - struct sigaction *oact) -{ - struct emulated_sigaction *k; - struct sigaction act1; - int host_sig; - - if (sig < 1 || sig > NSIG) - return -EINVAL; - - k = &sigact_table[sig - 1]; -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n", - sig, (int)act, (int)oact); -#endif - if (oact) { -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n", - sig, (int)act, (int)oact); -#endif - - oact->sa_handler = tswapl(k->sa.sa_handler); - oact->sa_flags = tswapl(k->sa.sa_flags); - oact->sa_mask = tswapl(k->sa.sa_mask); - } - if (act) { -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n", - act->sa_handler, act->sa_flags, act->sa_mask); -#endif - - k->sa.sa_handler = tswapl(act->sa_handler); - k->sa.sa_flags = tswapl(act->sa_flags); - k->sa.sa_mask = tswapl(act->sa_mask); - /* we update the host signal state */ - host_sig = target_to_host_signal(sig); - if (host_sig != SIGSEGV && host_sig != SIGBUS) { -#if defined(DEBUG_SIGNAL) - fprintf(stderr, "sigaction handler going to call sigaction\n"); -#endif - - sigfillset(&act1.sa_mask); - act1.sa_flags = SA_SIGINFO; - if (k->sa.sa_flags & SA_RESTART) - act1.sa_flags |= SA_RESTART; - /* NOTE: it is important to update the host kernel signal - ignore state to avoid getting unexpected interrupted - syscalls */ - if (k->sa.sa_handler == SIG_IGN) { - act1.sa_sigaction = (void *)SIG_IGN; - } else if (k->sa.sa_handler == SIG_DFL) { - act1.sa_sigaction = (void *)SIG_DFL; - } else { - act1.sa_sigaction = host_signal_handler; - } - sigaction(host_sig, &act1, NULL); - } - } - return 0; -} - - -#ifdef TARGET_I386 - -static inline void * -get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) -{ - /* XXX Fix that */ - if(target_sigaltstack_used.ss_flags & SA_DISABLE) - { - int esp; - /* Default to using normal stack */ - esp = env->regs[R_ESP]; - - return (void *)((esp - frame_size) & -8ul); - } - else - { - return target_sigaltstack_used.ss_sp; - } -} - -static void setup_frame(int sig, struct emulated_sigaction *ka, - void *set, CPUX86State *env) -{ - void *frame; - - fprintf(stderr, "setup_frame %d\n", sig); - frame = get_sigframe(ka, env, sizeof(*frame)); - - /* Set up registers for signal handler */ - env->regs[R_ESP] = (unsigned long) frame; - env->eip = (unsigned long) ka->sa.sa_handler; - - env->eflags &= ~TF_MASK; - - return; - -give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV /* , current */); -} - -long do_sigreturn(CPUX86State *env, int num) -{ - int i = 0; - struct target_sigcontext *scp = get_int_arg(&i, env); - /* XXX Get current signal number */ - /* XXX Adjust accordin to sc_onstack, sc_mask */ - if(tswapl(scp->sc_onstack) & 0x1) - target_sigaltstack_used.ss_flags |= ~SA_DISABLE; - else - target_sigaltstack_used.ss_flags &= SA_DISABLE; - int set = tswapl(scp->sc_eax); - sigprocmask(SIG_SETMASK, &set, NULL); - - fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx)); - fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi)); - fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip)); - - env->regs[R_EAX] = tswapl(scp->sc_eax); - env->regs[R_EBX] = tswapl(scp->sc_ebx); - env->regs[R_ECX] = tswapl(scp->sc_ecx); - env->regs[R_EDX] = tswapl(scp->sc_edx); - env->regs[R_EDI] = tswapl(scp->sc_edi); - env->regs[R_ESI] = tswapl(scp->sc_esi); - env->regs[R_EBP] = tswapl(scp->sc_ebp); - env->regs[R_ESP] = tswapl(scp->sc_esp); - env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss); - env->eflags = tswapl(scp->sc_eflags); - env->eip = tswapl(scp->sc_eip); - env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs); - env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds); - env->segs[R_ES].selector = (void*)tswapl(scp->sc_es); - env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs); - env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs); - - /* Again, because our caller's caller will reset EAX */ - return env->regs[R_EAX]; -} - -#else - -static void setup_frame(int sig, struct emulated_sigaction *ka, - void *set, CPUArchState *env) -{ - fprintf(stderr, "setup_frame: not implemented\n"); -} - -long do_sigreturn(CPUArchState *env, int num) -{ - int i = 0; - struct target_sigcontext *scp = get_int_arg(&i, env); - fprintf(stderr, "do_sigreturn: not implemented\n"); - return -ENOSYS; -} - -#endif - -void process_pending_signals(void *cpu_env) -{ - struct emulated_sigaction *k; - struct sigqueue *q; - target_ulong handler; - int sig; - - if (!signal_pending) - return; - - k = sigact_table; - - for(sig = 1; sig <= NSIG; sig++) { - if (k->pending) - goto handle_signal; - k++; - } - - /* if no signal is pending, just return */ - signal_pending = 0; - return; -handle_signal: - #ifdef DEBUG_SIGNAL - fprintf(stderr, "qemu: process signal %d\n", sig); - #endif - /* dequeue signal */ - q = k->first; - k->first = q->next; - if (!k->first) - k->pending = 0; - - sig = gdb_handlesig (cpu_env, sig); - if (!sig) { - fprintf (stderr, "Lost signal\n"); - abort(); - } - - handler = k->sa.sa_handler; - if (handler == SIG_DFL) { - /* default handler : ignore some signal. The other are fatal */ - if (sig != SIGCHLD && - sig != SIGURG && - sig != SIGWINCH) { - force_sig(sig); - } - } else if (handler == SIG_IGN) { - /* ignore sig */ - } else if (handler == SIG_ERR) { - force_sig(sig); - } else { - - setup_frame(sig, k, 0, cpu_env); - if (k->sa.sa_flags & SA_RESETHAND) - k->sa.sa_handler = SIG_DFL; - } - if (q != &k->info) - free_sigqueue(q); -} diff --git a/darwin-user/syscall.c b/darwin-user/syscall.c deleted file mode 100644 index 8a168830e9..0000000000 --- a/darwin-user/syscall.c +++ /dev/null @@ -1,1566 +0,0 @@ -/* - * 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, see <http://www.gnu.org/licenses/>. - */ -#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 { qemu_log(__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 { qemu_log(__VA_ARGS__); } while(0) -#endif - -enum { - 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 < ARRAY_SIZE(msg_name); 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 < ARRAY_SIZE(msg_name); 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); - data->cpu_subtype = CPU_SUBTYPE_POWERPC_750; - DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype); -#else -# error target not supported -#endif - break; - } - case 202: /* host_page_size */ - { - mig_reply_error_t *err = (mig_reply_error_t *)hdr; - uint32_t *pagesize = (uint32_t *)(err+1); - - DPRINTF("pagesize = %d\n", *pagesize); - break; - } - default: break; - } - - swap_mach_msg(hdr, bswap_out); - - return ret; -} - -long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, - uint32_t arg8) -{ - extern uint32_t mach_reply_port(void); - - long ret = 0; - - arg1 = tswap32(arg1); - arg2 = tswap32(arg2); - arg3 = tswap32(arg3); - arg4 = tswap32(arg4); - arg5 = tswap32(arg5); - arg6 = tswap32(arg6); - arg7 = tswap32(arg7); - arg8 = tswap32(arg8); - - DPRINTF("mach syscall %d : " , num); - - switch(num) { - /* see xnu/osfmk/mach/syscall_sw.h */ - case -26: - DPRINTF("mach_reply_port()\n"); - ret = mach_reply_port(); - break; - case -27: - DPRINTF("mach_thread_self()\n"); - ret = mach_thread_self(); - break; - case -28: - DPRINTF("mach_task_self()\n"); - ret = mach_task_self(); - break; - case -29: - DPRINTF("mach_host_self()\n"); - ret = mach_host_self(); - break; - case -31: - DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", - arg1, arg2, arg3, arg4, arg5, arg6, arg7); - ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7); - break; -/* may need more translation if target arch is different from host */ -#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) - case -33: - DPRINTF("semaphore_signal_trap(0x%x)\n", arg1); - ret = semaphore_signal_trap(arg1); - break; - case -34: - DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1); - ret = semaphore_signal_all_trap(arg1); - break; - case -35: - DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2); - ret = semaphore_signal_thread_trap(arg1,arg2); - break; -#endif - case -36: - DPRINTF("semaphore_wait_trap(0x%x)\n", arg1); - extern int semaphore_wait_trap(int); // XXX: is there any header for that? - ret = semaphore_wait_trap(arg1); - break; -/* may need more translation if target arch is different from host */ -#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) - case -37: - DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2); - ret = semaphore_wait_signal_trap(arg1,arg2); - break; -#endif - case -43: - DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", - arg1, arg2, arg3, arg4, arg5); - ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5); - tswap32s((uint32_t*)arg3); - break; -/* may need more translation if target arch is different from host */ -#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) - case -61: - DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n", - arg1, arg2, arg3); - ret = syscall_thread_switch(arg1, arg2, arg3); // just a hint to the scheduler; can drop? - break; -#endif - case -89: - DPRINTF("mach_timebase_info(0x%x)\n", arg1); - struct mach_timebase_info info; - ret = mach_timebase_info(&info); - if(!is_error(ret)) - { - struct mach_timebase_info *outInfo = (void*)arg1; - outInfo->numer = tswap32(info.numer); - outInfo->denom = tswap32(info.denom); - } - break; - case -90: - DPRINTF("mach_wait_until()\n"); - extern int mach_wait_until(uint64_t); // XXX: is there any header for that? - ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1); - break; - case -91: - DPRINTF("mk_timer_create()\n"); - extern int mk_timer_create(); // XXX: is there any header for that? - ret = mk_timer_create(); - break; - case -92: - DPRINTF("mk_timer_destroy()\n"); - extern int mk_timer_destroy(int); // XXX: is there any header for that? - ret = mk_timer_destroy(arg1); - break; - case -93: - DPRINTF("mk_timer_create()\n"); - extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that? - ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2); - break; - case -94: - DPRINTF("mk_timer_cancel()\n"); - extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that? - ret = mk_timer_cancel(arg1, (uint64_t *)arg2); - if((!is_error(ret)) && arg2) - tswap64s((uint64_t *)arg2); - break; - default: - gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num); - gdb_handlesig (cpu_env, SIGTRAP); - exit(0); - break; - } - return ret; -} - -/* ------------------------------------------------------------ - thread type syscall handling -*/ -long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, - uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, - uint32_t arg8) -{ - extern uint32_t cthread_set_self(uint32_t); - extern uint32_t processor_facilities_used(void); - long ret = 0; - - arg1 = tswap32(arg1); - arg2 = tswap32(arg2); - arg3 = tswap32(arg3); - arg4 = tswap32(arg4); - arg5 = tswap32(arg5); - arg6 = tswap32(arg6); - arg7 = tswap32(arg7); - arg8 = tswap32(arg8); - - DPRINTF("thread syscall %d : " , num); - - switch(num) { -#ifdef TARGET_I386 - case 0x3: -#endif - case 0x7FF1: /* cthread_set_self */ - DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1); - ret = cthread_set_self(arg1); -#ifdef TARGET_I386 - /* we need to update the LDT with the address of the thread */ - write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1, - DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | - (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); - /* New i386 convention, %gs should be set to our this LDT entry */ - cpu_x86_load_seg(cpu_env, R_GS, 0x27); - /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/ - ret = 0x27; -#endif - break; - case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */ - DPRINTF("pthread_self()\n"); - ret = (uint32_t)pthread_self(); - break; - case 0x7FF3: - DPRINTF("processor_facilities_used()\n"); -#ifdef __i386__ - qerror("processor_facilities_used: not implemented!\n"); -#else - ret = (uint32_t)processor_facilities_used(); -#endif - break; - default: - gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num); - gdb_handlesig (cpu_env, SIGTRAP); - exit(0); - break; - } - return ret; -} - -/* ------------------------------------------------------------ - ioctl handling -*/ -static inline void byteswap_termios(struct termios *t) -{ - tswap32s((uint32_t*)&t->c_iflag); - tswap32s((uint32_t*)&t->c_oflag); - tswap32s((uint32_t*)&t->c_cflag); - tswap32s((uint32_t*)&t->c_lflag); - /* 20 (char) bytes then */ - tswap32s((uint32_t*)&t->c_ispeed); - tswap32s((uint32_t*)&t->c_ospeed); -} - -static inline void byteswap_winsize(struct winsize *w) -{ - tswap16s(&w->ws_row); - tswap16s(&w->ws_col); - tswap16s(&w->ws_xpixel); - tswap16s(&w->ws_ypixel); -} - -#define STRUCT(name, ...) STRUCT_ ## name, -#define STRUCT_SPECIAL(name) STRUCT_ ## name, -enum { -#include "ioctls_types.h" -}; -#undef STRUCT -#undef STRUCT_SPECIAL - -#define STRUCT(name, ...) const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL }; -#define STRUCT_SPECIAL(name) -#include "ioctls_types.h" -#undef STRUCT -#undef STRUCT_SPECIAL - -typedef struct IOCTLEntry { - unsigned int target_cmd; - unsigned int host_cmd; - const char *name; - int access; - const argtype arg_type[5]; -} IOCTLEntry; - -#define IOC_R 0x0001 -#define IOC_W 0x0002 -#define IOC_RW (IOC_R | IOC_W) - -#define MAX_STRUCT_SIZE 4096 - -static IOCTLEntry ioctl_entries[] = { -#define IOCTL(cmd, access, ...) \ - { cmd, cmd, #cmd, access, { __VA_ARGS__ } }, -#include "ioctls.h" - { 0, 0, }, -}; - -/* ??? Implement proper locking for ioctls. */ -static long do_ioctl(long fd, long cmd, long arg) -{ - const IOCTLEntry *ie; - const argtype *arg_type; - int ret; - uint8_t buf_temp[MAX_STRUCT_SIZE]; - int target_size; - void *argptr; - - ie = ioctl_entries; - for(;;) { - if (ie->target_cmd == 0) { - gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd); - return -ENOSYS; - } - if (ie->target_cmd == cmd) - break; - ie++; - } - arg_type = ie->arg_type; -#if defined(DEBUG) - gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name); -#endif - switch(arg_type[0]) { - case TYPE_NULL: - /* no argument */ - ret = get_errno(ioctl(fd, ie->host_cmd)); - break; - case TYPE_PTRVOID: - case TYPE_INT: - /* int argment */ - ret = get_errno(ioctl(fd, ie->host_cmd, arg)); - break; - case TYPE_PTR: - arg_type++; - target_size = thunk_type_size(arg_type, 0); - switch(ie->access) { - case IOC_R: - ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); - if (!is_error(ret)) { - argptr = lock_user(arg, target_size, 0); - thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); - unlock_user(argptr, arg, target_size); - } - break; - case IOC_W: - argptr = lock_user(arg, target_size, 1); - thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); - unlock_user(argptr, arg, 0); - ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); - break; - default: - case IOC_RW: - argptr = lock_user(arg, target_size, 1); - thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); - unlock_user(argptr, arg, 0); - ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); - if (!is_error(ret)) { - argptr = lock_user(arg, target_size, 0); - thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); - unlock_user(argptr, arg, target_size); - } - break; - } - break; - default: - gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]); - ret = -ENOSYS; - break; - } - return ret; -} - -/* ------------------------------------------------------------ - Unix syscall handling -*/ - -static inline void byteswap_attrlist(struct attrlist *a) -{ - tswap16s(&a->bitmapcount); - tswap16s(&a->reserved); - tswap32s(&a->commonattr); - tswap32s(&a->volattr); - tswap32s(&a->dirattr); - tswap32s(&a->fileattr); - tswap32s(&a->forkattr); -} - -struct attrbuf_header { - unsigned long length; -}; - -static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist) -{ - DPRINTF("attrBuf.length %lx\n", attrbuf->length); -} - -static inline void byteswap_statfs(struct statfs *s) -{ - tswap16s((uint16_t*)&s->f_otype); - tswap16s((uint16_t*)&s->f_oflags); - tswap32s((uint32_t*)&s->f_bsize); - tswap32s((uint32_t*)&s->f_iosize); - tswap32s((uint32_t*)&s->f_blocks); - tswap32s((uint32_t*)&s->f_bfree); - tswap32s((uint32_t*)&s->f_bavail); - tswap32s((uint32_t*)&s->f_files); - tswap32s((uint32_t*)&s->f_ffree); - tswap32s((uint32_t*)&s->f_fsid.val[0]); - tswap32s((uint32_t*)&s->f_fsid.val[1]); - tswap16s((uint16_t*)&s->f_reserved1); - tswap16s((uint16_t*)&s->f_type); - tswap32s((uint32_t*)&s->f_flags); -} - -static inline void byteswap_stat(struct stat *s) -{ - tswap32s((uint32_t*)&s->st_dev); - tswap32s(&s->st_ino); - tswap16s(&s->st_mode); - tswap16s(&s->st_nlink); - tswap32s(&s->st_uid); - tswap32s(&s->st_gid); - tswap32s((uint32_t*)&s->st_rdev); - tswap32s((uint32_t*)&s->st_atimespec.tv_sec); - tswap32s((uint32_t*)&s->st_atimespec.tv_nsec); - tswap32s((uint32_t*)&s->st_mtimespec.tv_sec); - tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec); - tswap32s((uint32_t*)&s->st_ctimespec.tv_sec); - tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec); - tswap64s((uint64_t*)&s->st_size); - tswap64s((uint64_t*)&s->st_blocks); - tswap32s((uint32_t*)&s->st_blksize); - tswap32s(&s->st_flags); - tswap32s(&s->st_gen); -} - -static inline void byteswap_dirents(struct dirent *d, int bytes) -{ - char *b; - for( b = (char*)d; (int)b < (int)d+bytes; ) - { - unsigned short s = ((struct dirent *)b)->d_reclen; - tswap32s(&((struct dirent *)b)->d_ino); - tswap16s(&((struct dirent *)b)->d_reclen); - if(s<=0) - break; - b += s; - } -} - -static inline void byteswap_iovec(struct iovec *v, int n) -{ - int i; - for(i = 0; i < n; i++) - { - tswap32s((uint32_t*)&v[i].iov_base); - tswap32s((uint32_t*)&v[i].iov_len); - } -} - -static inline void byteswap_timeval(struct timeval *t) -{ - tswap32s((uint32_t*)&t->tv_sec); - tswap32s((uint32_t*)&t->tv_usec); -} - -long do_unix_syscall_indirect(void *cpu_env, int num); -long do_sync(void); -long do_exit(uint32_t arg1); -long do_getlogin(char *out, uint32_t size); -long do_open(char * arg1, uint32_t arg2, uint32_t arg3); -long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3); -long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3); -long do_execve(char* arg1, char ** arg2, char ** arg3); -long do_getgroups(uint32_t arg1, gid_t * arg2); -long do_gettimeofday(struct timeval * arg1, void * arg2); -long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3); -long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3); -long do_utimes(char * arg1, struct timeval * arg2); -long do_futimes(uint32_t arg1, struct timeval * arg2); -long do_statfs(char * arg1, struct statfs * arg2); -long do_fstatfs(uint32_t arg1, struct statfs * arg2); -long do_stat(char * arg1, struct stat * arg2); -long do_fstat(uint32_t arg1, struct stat * arg2); -long do_lstat(char * arg1, struct stat * arg2); -long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4); -long do_lseek(void *cpu_env, int num); -long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */); -long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5); -long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8); -long do_fcntl(int fd, int cmd, int arg); - -long no_syscall(void *cpu_env, int num); - -long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4) -{ - DPRINTF("0x%x, %p, 0x%lx, 0x%" PRIx64 "\n", arg1, arg2, arg3, arg4); - long ret = pread(arg1, arg2, arg3, arg4); - return ret; -} - -long do_read(int d, void *buf, size_t nbytes) -{ - DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes); - long ret = get_errno(read(d, buf, nbytes)); - if(!is_error(ret)) - DPRINTF("%x\n", *(uint32_t*)buf); - return ret; -} - -long unimpl_unix_syscall(void *cpu_env, int num); - -typedef long (*syscall_function_t)(void *cpu_env, int num); - - -/* define a table that will handle the syscall number->function association */ -#define VOID void -#define INT (uint32_t)get_int_arg(&i, cpu_env) -#define INT64 (uint64_t)get_int64_arg(&i, cpu_env) -#define UINT (unsigned int)INT -#define PTR (void*)INT - -#define SIZE INT -#define OFFSET INT64 - -#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) { return (long)function(); } -#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; return (long)function(arg1); } -#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); } -#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); } -#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); } -#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); } -#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); } -#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); } -#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); } -#define WRAPPER_CALL_DIRECT(function, nargs, ...) WRAPPER_CALL_DIRECT_##nargs(function, __VA_ARGS__) -#define WRAPPER_CALL_NOERRNO(function, nargs, ...) WRAPPER_CALL_DIRECT(function, nargs, __VA_ARGS__) -#define WRAPPER_CALL_INDIRECT(function, nargs, ...) -#define ENTRY(name, number, function, nargs, call_type, ...) WRAPPER_##call_type(function, nargs, __VA_ARGS__) - -#include "syscalls.h" - -#undef ENTRY -#undef WRAPPER_CALL_DIRECT -#undef WRAPPER_CALL_NOERRNO -#undef WRAPPER_CALL_INDIRECT -#undef OFFSET -#undef SIZE -#undef INT -#undef PTR -#undef INT64 - -#define _ENTRY(name, number, function, nargs, call_type) [number] = {\ - name, \ - number, \ - (syscall_function_t)function, \ - nargs, \ - call_type \ - }, - -#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, __qemu_##function, nargs, call_type) -#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) -#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type) -#define ENTRY(name, number, function, nargs, call_type, ...) ENTRY_##call_type(name, number, function, nargs, call_type) - -#define CALL_DIRECT 1 -#define CALL_INDIRECT 2 -#define CALL_NOERRNO (CALL_DIRECT | 4 /* = 5 */) - -struct unix_syscall { - char * name; - int number; - syscall_function_t function; - int nargs; - int call_type; -} unix_syscall_table[SYS_MAXSYSCALL] = { -#include "syscalls.h" -}; - -#undef ENTRY -#undef _ENTRY -#undef ENTRY_CALL_DIRECT -#undef ENTRY_CALL_INDIRECT -#undef ENTRY_CALL_NOERRNO - -/* Actual syscalls implementation */ - -long do_unix_syscall_indirect(void *cpu_env, int num) -{ - long ret; - int new_num; - int i = 0; - - new_num = get_int_arg(&i, cpu_env); -#ifdef TARGET_I386 - ((CPUX86State*)cpu_env)->regs[R_ESP] += 4; - /* XXX: not necessary */ - ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num; -#elif TARGET_PPC - { - int i; - uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr; - for(i = 3; i < 11; i++) - *regs[i] = *regs[i+1]; - /* XXX: not necessary */ - *regs[0] = new_num; - } -#endif - ret = do_unix_syscall(cpu_env, new_num); -#ifdef TARGET_I386 - ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4; - /* XXX: not necessary */ - ((CPUX86State*)cpu_env)->regs[R_EAX] = num; -#elif TARGET_PPC - { - int i; - /* XXX: not really needed those regs are volatile across calls */ - uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr; - for(i = 11; i > 3; i--) - *regs[i] = *regs[i-1]; - regs[3] = new_num; - *regs[0] = num; - } -#endif - return ret; -} - -long do_exit(uint32_t arg1) -{ - exit(arg1); - /* not reached */ - return -1; -} - -long do_sync(void) -{ - sync(); - return 0; -} - -long do_getlogin(char *out, uint32_t size) -{ - char *login = getlogin(); - if(!login) - return -1; - memcpy(out, login, size); - return 0; -} -long do_open(char * arg1, uint32_t arg2, uint32_t arg3) -{ - /* XXX: don't let the %s stay in there */ - DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3); - return get_errno(open(arg1, arg2, arg3)); -} - -long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3) -{ - long ret; - DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3); - ret = get_errno(getfsstat(arg1, arg2, arg3)); - if((!is_error(ret)) && arg1) - byteswap_statfs(arg1); - return ret; -} - -long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3) -{ - long ret; - DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3); - gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3); - if(arg2) - tswap32s(arg2); - ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3)); - if((!is_error(ret)) && arg3) - tswap32s(arg3); - if(arg2) - tswap32s(arg2); - return ret; -} - -long do_execve(char* arg1, char ** arg2, char ** arg3) -{ - long ret; - char **argv = arg2; - char **envp = arg3; - int argc; - int envc; - - /* XXX: don't let the %s stay in here */ - DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3); - - for(argc = 0; argv[argc]; argc++); - for(envc = 0; envp[envc]; envc++); - - argv = (char**)malloc(sizeof(char*)*argc); - envp = (char**)malloc(sizeof(char*)*envc); - - for(; argc >= 0; argc--) - argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]); - - for(; envc >= 0; envc--) - envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]); - - ret = get_errno(execve(arg1, argv, envp)); - free(argv); - free(envp); - return ret; -} - -long do_getgroups(uint32_t arg1, gid_t * arg2) -{ - long ret; - int i; - DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2); - ret = get_errno(getgroups(arg1, arg2)); - if(ret > 0) - for(i = 0; i < arg1; i++) - tswap32s(&arg2[i]); - return ret; -} - -long do_gettimeofday(struct timeval * arg1, void * arg2) -{ - long ret; - DPRINTF("gettimeofday(%p, %p)\n", - arg1, arg2); - ret = get_errno(gettimeofday(arg1, arg2)); - if(!is_error(ret)) - { - /* timezone no longer used according to the manpage, so don't bother with it */ - byteswap_timeval(arg1); - } - return ret; -} - -long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3) -{ - long ret; - DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3); - if(arg2) - byteswap_iovec(arg2, arg3); - ret = get_errno(readv(arg1, arg2, arg3)); - if((!is_error(ret)) && arg2) - byteswap_iovec(arg2, arg3); - return ret; -} - -long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3) -{ - long ret; - DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3); - if(arg2) - byteswap_iovec(arg2, arg3); - ret = get_errno(writev(arg1, arg2, arg3)); - if((!is_error(ret)) && arg2) - byteswap_iovec(arg2, arg3); - return ret; -} - -long do_utimes(char * arg1, struct timeval * arg2) -{ - DPRINTF("utimes(%p, %p)\n", arg1, arg2); - if(arg2) - { - byteswap_timeval(arg2); - byteswap_timeval(arg2+1); - } - return get_errno(utimes(arg1, arg2)); -} - -long do_futimes(uint32_t arg1, struct timeval * arg2) -{ - DPRINTF("futimes(0x%x, %p)\n", arg1, arg2); - if(arg2) - { - byteswap_timeval(arg2); - byteswap_timeval(arg2+1); - } - return get_errno(futimes(arg1, arg2)); -} - -long do_statfs(char * arg1, struct statfs * arg2) -{ - long ret; - DPRINTF("statfs(%p, %p)\n", arg1, arg2); - ret = get_errno(statfs(arg1, arg2)); - if(!is_error(ret)) - byteswap_statfs(arg2); - return ret; -} - -long do_fstatfs(uint32_t arg1, struct statfs* arg2) -{ - long ret; - DPRINTF("fstatfs(0x%x, %p)\n", - arg1, arg2); - ret = get_errno(fstatfs(arg1, arg2)); - if(!is_error(ret)) - byteswap_statfs(arg2); - - return ret; -} - -long do_stat(char * arg1, struct stat * arg2) -{ - long ret; - /* XXX: don't let the %s stay in there */ - DPRINTF("stat(%s, %p)\n", arg1, arg2); - ret = get_errno(stat(arg1, arg2)); - if(!is_error(ret)) - byteswap_stat(arg2); - return ret; -} - -long do_fstat(uint32_t arg1, struct stat * arg2) -{ - long ret; - DPRINTF("fstat(0x%x, %p)\n", arg1, arg2); - ret = get_errno(fstat(arg1, arg2)); - if(!is_error(ret)) - byteswap_stat(arg2); - return ret; -} - -long do_lstat(char * arg1, struct stat * arg2) -{ - long ret; - /* XXX: don't let the %s stay in there */ - DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2); - ret = get_errno(lstat(arg1, arg2)); - if(!is_error(ret)) - byteswap_stat(arg2); - return ret; -} - -long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4) -{ - long ret; - DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4); - if(arg4) - tswap32s((uint32_t *)arg4); - ret = get_errno(getdirentries(arg1, arg2, arg3, arg4)); - if(arg4) - tswap32s((uint32_t *)arg4); - if(!is_error(ret)) - byteswap_dirents(arg2, ret); - return ret; -} - -long do_lseek(void *cpu_env, int num) -{ - long ret; - int i = 0; - uint32_t arg1 = get_int_arg(&i, cpu_env); - uint64_t offset = get_int64_arg(&i, cpu_env); - uint32_t arg3 = get_int_arg(&i, cpu_env); - uint64_t r = lseek(arg1, offset, arg3); -#ifdef TARGET_I386 - /* lowest word in eax, highest in edx */ - ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */ - ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ; -#elif defined TARGET_PPC - ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */ - ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ; -#else - qerror("64 bit ret value on your arch?"); -#endif - return get_errno(ret); -} - -void no_swap(void * oldp, int size) -{ -} - -void sysctl_tswap32s(void * oldp, int size) -{ - tswap32s(oldp); -} - -void bswap_oid(uint32_t * oldp, int size) -{ - int count = size / sizeof(int); - int i = 0; - do { tswap32s(oldp + i); } while (++i < count); -} - -void sysctl_usrstack(uint32_t * oldp, int size) -{ - DPRINTF("sysctl_usrstack: 0x%x\n", *oldp); - tswap32s(oldp); -} - -void sysctl_ncpu(uint32_t * ncpu, int size) -{ - *ncpu = 0x1; - DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu); - tswap32s(ncpu); -} - -void sysctl_exec(char * exec, int size) -{ - DPRINTF("sysctl_exec: %s\n", exec); -} - -void sysctl_translate(char * exec, int size) -{ - DPRINTF("sysctl_translate: %s\n", exec); -} - -struct sysctl_dir { - int num; - const char * name; - void (*swap_func)(void *, int); - struct sysctl_dir *childs; -}; - -#define ENTRYD(num, name, childs) { num, name, NULL, childs } -#define ENTRYE(num, name, func) { num, name, (void (*)(void *, int))func, NULL } -struct sysctl_dir sysctls_unspec[] = { - ENTRYE(3, "oip", bswap_oid), - { 0, NULL, NULL, NULL } -}; - -struct sysctl_dir sysctls_kern[] = { - ENTRYE(KERN_TRANSLATE, "translate", sysctl_translate), /* 44 */ - ENTRYE(KERN_EXEC, "exec", sysctl_exec), /* 45 */ - ENTRYE(KERN_USRSTACK32, "KERN_USRSTACK32", sysctl_usrstack), /* 35 */ - ENTRYE(KERN_SHREG_PRIVATIZABLE, "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */ - { 0, NULL, NULL, NULL } -}; - -struct sysctl_dir sysctls_hw[] = { - ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s), - ENTRYE(104, "104", no_swap), - ENTRYE(105, "105", no_swap), - { 0, NULL, NULL, NULL } -}; - -struct sysctl_dir sysctls[] = { - ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec), - ENTRYD(CTL_KERN, "kern", sysctls_kern), - ENTRYD(CTL_HW, "hw", sysctls_hw ), - { 0, NULL, NULL, NULL } -}; - -#undef ENTRYE -#undef ENTRYD - -static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt) -{ - if(!sysctl_elmt) - return NULL; - for(; sysctl_elmt->name != NULL ; sysctl_elmt++) { - if(sysctl_elmt->num == mib) - return sysctl_elmt; - } - return NULL; -} - -static inline long bswap_syctl(int * mib, int count, void *buf, int size) -{ - int i; - struct sysctl_dir * sysctl = sysctls; - struct sysctl_dir * ret = NULL; - - for(i = 0; i < count; i++) { - - if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) { - gemu_log("bswap_syctl: can't find mib %d\n", mib[i]); - return -ENOTDIR; - } - if(!(sysctl = sysctl->childs)) - break; - } - - if(ret->childs) - qerror("we shouldn't have a directory element\n"); - - ret->swap_func(buf, size); - return 0; -} - -static inline void print_syctl(int * mib, int count) -{ - int i; - struct sysctl_dir * sysctl = sysctls; - struct sysctl_dir * ret = NULL; - - for(i = 0; i < count; i++) { - if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){ - gemu_log("print_syctl: can't find mib %d\n", mib[i]); - return; - } - DPRINTF("%s.", sysctl->name); - if(!(sysctl = sysctl->childs)) - break; - } - DPRINTF("\n"); -} - -long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen /* ignored */) -{ - long ret = 0; - int i; - DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n", - name, namelen, oldp, oldlenp, newp, newlen); - if(name) { - i = 0; - do { tswap32s( name + i); } while (++i < namelen); - print_syctl(name, namelen); - //bswap_syctl(name, namelen, newp, newlen); - tswap32s((uint32_t*)oldlenp); - } - - if(name) /* Sometimes sysctl is called with no arg1, ignore */ - ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen)); - -#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__) - if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) { - return -ENOTDIR; - } -#endif - - if(name) { - //bswap_syctl(name, namelen, newp, newlen); - tswap32s((uint32_t*)oldlenp); - - i = 0; - do { tswap32s( name + i); } while (++i < namelen); - } - return ret; -} - -long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5) -{ - struct attrlist * attrlist = (void *)arg2; - long ret; - -#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__) - gemu_log("SYS_getdirentriesattr unimplemented\n"); - return -ENOTSUP; -#endif - /* XXX: don't let the %s stay in there */ - DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n", - (char *)arg1, arg2, arg3, arg4, arg5); - - if(arg2) /* XXX: We should handle that in a copy especially - if the structure is not writable */ - byteswap_attrlist(attrlist); - - ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5)); - - if(!is_error(ret)) - { - byteswap_attrbuf((void *)arg3, attrlist); - byteswap_attrlist(attrlist); - } - return ret; -} - -long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8) -{ - DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n", - arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); -#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__) - qerror("SYS_getdirentriesattr unimplemented\n"); -#endif - - return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4, - (unsigned long *)arg5, (unsigned long *)arg6, - (unsigned long *)arg7, arg8)); -} - -static inline void bswap_flock(struct flock *f) -{ - tswap64s(&f->l_start); - tswap64s(&f->l_len); - tswap32s(&f->l_pid); - tswap16s(&f->l_type); - tswap16s(&f->l_whence); -} - -static inline void bswap_fstore(struct fstore *f) -{ - tswap32s(&f->fst_flags); - tswap32s(&f->fst_posmode); - tswap64s(&f->fst_offset); - tswap64s(&f->fst_length); - tswap64s(&f->fst_bytesalloc); -} - -static inline void bswap_radvisory(struct radvisory *f) -{ - tswap64s(&f->ra_offset); - tswap32s(&f->ra_count); -} - -static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f) -{ - tswap64s(&f->fbt_offset); - tswap32s((uint32_t*)&f->fbt_length); - tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */ -} - -static inline void bswap_log2phys(struct log2phys *f) -{ - tswap32s(&f->l2p_flags); - tswap64s(&f->l2p_contigbytes); - tswap64s(&f->l2p_devoffset); -} - -static inline void bswap_fcntl_arg(int cmd, void * arg) -{ - switch(cmd) - { - case F_DUPFD: - case F_GETFD: - case F_SETFD: - case F_GETFL: - case F_SETFL: - case F_GETOWN: - case F_SETOWN: - case F_SETSIZE: - case F_RDAHEAD: - case F_FULLFSYNC: - break; - case F_GETLK: - case F_SETLK: - case F_SETLKW: - bswap_flock(arg); - break; - case F_PREALLOCATE: - bswap_fstore(arg); - break; - case F_RDADVISE: - bswap_radvisory(arg); - break; - case F_READBOOTSTRAP: - case F_WRITEBOOTSTRAP: - bswap_fbootstraptransfer(arg); - break; - case F_LOG2PHYS: - bswap_log2phys(arg); - break; - default: - gemu_log("unknow cmd in fcntl\n"); - } -} - -long do_fcntl(int fd, int cmd, int arg) -{ - long ret; - bswap_fcntl_arg(cmd, (void *)arg); - ret = get_errno(fcntl(fd, cmd, arg)); - if(!is_error(ret)) - bswap_fcntl_arg(cmd, (void *)arg); - return ret; -} - -long no_syscall(void *cpu_env, int num) -{ - /* XXX: We should probably fordward it to the host kernel */ - qerror("no unix syscall %d\n", num); - /* not reached */ - return -1; -} - -long unimpl_unix_syscall(void *cpu_env, int num) -{ - if( (num < 0) || (num > SYS_MAXSYSCALL-1) ) - qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1); - - gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num); - gdb_handlesig (cpu_env, SIGTRAP); - exit(-1); -} - -long do_unix_syscall(void *cpu_env, int num) -{ - long ret = 0; - - DPRINTF("unix syscall %d: " , num); - - if( (num < 0) || (num > SYS_MAXSYSCALL-1) ) - qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1); - - DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" ); - ret = unix_syscall_table[num].function(cpu_env, num); - - if(!(unix_syscall_table[num].call_type & CALL_NOERRNO)) - ret = get_errno(ret); - - DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret); - return ret; -} - -/* ------------------------------------------------------------ - syscall_init -*/ -void syscall_init(void) -{ - /* Nothing yet */ -} diff --git a/darwin-user/syscalls.h b/darwin-user/syscalls.h deleted file mode 100644 index 34d95daa7d..0000000000 --- a/darwin-user/syscalls.h +++ /dev/null @@ -1,384 +0,0 @@ -/* generated from xnu/bsd/kern/syscalls.master */ - - ENTRY("syscall", SYS_syscall, do_unix_syscall_indirect, 0, CALL_INDIRECT, VOID) /* 0 indirect syscall */ - ENTRY("exit", SYS_exit, do_exit, 1, CALL_DIRECT, INT) /* 1 */ - ENTRY("fork", SYS_fork, fork, 0, CALL_NOERRNO, VOID) /* 2 */ - ENTRY("read", SYS_read, do_read, 3, CALL_DIRECT, INT, PTR, SIZE) /* 3 */ - ENTRY("write", SYS_write, write, 3, CALL_DIRECT, INT, PTR, SIZE) /* 4 */ - ENTRY("open", SYS_open, do_open, 3, CALL_DIRECT, PTR, INT, INT) /* 5 */ - ENTRY("close", SYS_close, close, 1, CALL_DIRECT, INT) /* 6 */ - ENTRY("wait4", SYS_wait4, wait4, 4, CALL_DIRECT, INT, PTR, INT, PTR) /* 7 */ - ENTRY("", 8, no_syscall, 0, CALL_INDIRECT, VOID) /* 8 old creat */ - ENTRY("link", SYS_link, link, 2, CALL_DIRECT, PTR, PTR) /* 9 */ - ENTRY("unlink", SYS_unlink, unlink, 1, CALL_DIRECT, PTR) /* 10 */ - ENTRY("", 11, no_syscall, 0, CALL_INDIRECT, VOID) /* 11 old execv */ - ENTRY("chdir", SYS_chdir, chdir, 1, CALL_DIRECT, PTR) /* 12 */ - ENTRY("fchdir", SYS_fchdir, fchdir, 1, CALL_DIRECT, INT) /* 13 */ - ENTRY("mknod", SYS_mknod, mknod, 3, CALL_DIRECT, PTR, INT, INT) /* 14 */ - ENTRY("chmod", SYS_chmod, chmod, 2, CALL_DIRECT, PTR, INT) /* 15 */ - ENTRY("chown", SYS_chown, chown, 3, CALL_DIRECT, PTR, INT, INT) /* 16 */ - ENTRY("obreak", SYS_obreak, no_syscall, 1, CALL_INDIRECT, VOID) /* 17 old break */ - ENTRY("ogetfsstat", 18, unimpl_unix_syscall, 3, CALL_INDIRECT, PTR, INT, INT) /* 18 */ - ENTRY("", 19, no_syscall, 0, CALL_INDIRECT, VOID) /* 19 old lseek */ - ENTRY("getpid", SYS_getpid, getpid, 0, CALL_NOERRNO, VOID) /* 20 */ - ENTRY("", 21, no_syscall, 0, CALL_INDIRECT, VOID) /* 21 old mount */ - ENTRY("", 22, no_syscall, 0, CALL_INDIRECT, VOID) /* 22 old umount */ - ENTRY("setuid", SYS_setuid, setuid, 1, CALL_DIRECT, INT) /* 23 */ - ENTRY("getuid", SYS_getuid, getuid, 0, CALL_NOERRNO, VOID) /* 24 */ - ENTRY("geteuid", SYS_geteuid, geteuid, 0, CALL_NOERRNO, VOID) /* 25 */ - ENTRY("ptrace", SYS_ptrace, ptrace, 4, CALL_DIRECT, INT, INT, PTR, INT) /* 26 */ - ENTRY("recvmsg", SYS_recvmsg, recvmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 27 */ - ENTRY("sendmsg", SYS_sendmsg, sendmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 28 */ - ENTRY("recvfrom", SYS_recvfrom, recvfrom, 6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR) /* 29 */ - ENTRY("accept", SYS_accept, accept, 3, CALL_DIRECT, INT, PTR, PTR) /* 30 */ - ENTRY("getpeername", SYS_getpeername, getpeername, 3, CALL_DIRECT, INT, PTR, PTR) /* 31 */ - ENTRY("getsockname", SYS_getsockname, getsockname, 3, CALL_DIRECT, INT, PTR, PTR) /* 32 */ - ENTRY("access", SYS_access, access, 2, CALL_DIRECT, PTR, INT) /* 33 */ - ENTRY("chflags", SYS_chflags, chflags, 2, CALL_DIRECT, PTR, INT) /* 34 */ - ENTRY("fchflags", SYS_fchflags, fchflags, 2, CALL_DIRECT, INT, INT) /* 35 */ - ENTRY("sync", SYS_sync, do_sync, 0, CALL_INDIRECT, VOID) /* 36 */ - ENTRY("kill", SYS_kill, kill, 2, CALL_DIRECT, INT, INT) /* 37 */ - ENTRY("", 38, no_syscall, 0, CALL_INDIRECT, VOID) /* 38 old stat */ - ENTRY("getppid", SYS_getppid, getppid, 0, CALL_DIRECT, VOID) /* 39 */ - ENTRY("", 40, no_syscall, 0, CALL_INDIRECT, VOID) /* 40 old lstat */ - ENTRY("dup", SYS_dup, dup, 1, CALL_DIRECT, INT) /* 41 */ - ENTRY("pipe", SYS_pipe, pipe, 0, CALL_INDIRECT, PTR) /* 42 */ - ENTRY("getegid", SYS_getegid, getegid, 0, CALL_NOERRNO, VOID) /* 43 */ - ENTRY("profil", SYS_profil, profil, 4, CALL_DIRECT, PTR, SIZE, INT, INT) /* 44 */ - ENTRY("ktrace", SYS_ktrace, no_syscall, 4, CALL_INDIRECT, VOID) /* 45 */ - ENTRY("sigaction", SYS_sigaction, do_sigaction, 3, CALL_DIRECT, INT, PTR, PTR) /* 46 */ - ENTRY("getgid", SYS_getgid, getgid, 0, CALL_NOERRNO, VOID) /* 47 */ - ENTRY("sigprocmask", SYS_sigprocmask, do_sigprocmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 48 */ - ENTRY("getlogin", SYS_getlogin, do_getlogin, 2, CALL_DIRECT, PTR, UINT) /* 49 XXX */ - ENTRY("setlogin", SYS_setlogin, setlogin, 1, CALL_DIRECT, PTR) /* 50 */ - ENTRY("acct", SYS_acct, acct, 1, CALL_DIRECT, PTR) /* 51 */ - ENTRY("sigpending", SYS_sigpending, sigpending, 1, CALL_DIRECT, PTR) /* 52 */ - ENTRY("sigaltstack", SYS_sigaltstack, do_sigaltstack, 2, CALL_DIRECT, PTR, PTR) /* 53 */ - ENTRY("ioctl", SYS_ioctl, do_ioctl, 3, CALL_DIRECT, INT, INT, INT) /* 54 */ - ENTRY("reboot", SYS_reboot, unimpl_unix_syscall, 2, CALL_INDIRECT, INT, PTR) /* 55 */ - ENTRY("revoke", SYS_revoke, revoke, 1, CALL_DIRECT, PTR) /* 56 */ - ENTRY("symlink", SYS_symlink, symlink, 2, CALL_DIRECT, PTR, PTR) /* 57 */ - ENTRY("readlink", SYS_readlink, readlink, 3, CALL_DIRECT, PTR, PTR, INT) /* 58 */ - ENTRY("execve", SYS_execve, do_execve, 3, CALL_DIRECT, PTR, PTR, PTR) /* 59 */ - ENTRY("umask", SYS_umask, umask, 1, CALL_DIRECT, INT) /* 60 */ - ENTRY("chroot", SYS_chroot, chroot, 1, CALL_DIRECT, PTR) /* 61 */ - ENTRY("", 62, no_syscall, 0, CALL_INDIRECT, VOID) /* 62 old fstat */ - ENTRY("", 63, no_syscall, 0, CALL_INDIRECT, VOID) /* 63 used internally , reserved */ - ENTRY("", 64, no_syscall, 0, CALL_INDIRECT, VOID) /* 64 old getpagesize */ - ENTRY("msync", SYS_msync, target_msync, 3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT) /* 65 */ - ENTRY("vfork", SYS_vfork, vfork, 0, CALL_DIRECT, VOID) /* 66 */ - ENTRY("", 67, no_syscall, 0, CALL_INDIRECT, VOID) /* 67 old vread */ - ENTRY("", 68, no_syscall, 0, CALL_INDIRECT, VOID) /* 68 old vwrite */ - ENTRY("sbrk", SYS_sbrk, sbrk, 1, CALL_DIRECT, INT) /* 69 */ - ENTRY("sstk", SYS_sstk, no_syscall, 1, CALL_INDIRECT, VOID) /* 70 */ - ENTRY("", 71, no_syscall, 0, CALL_INDIRECT, VOID) /* 71 old mmap */ - ENTRY("ovadvise", SYS_ovadvise, no_syscall, 0, CALL_INDIRECT, VOID) /* 72 old vadvise */ - ENTRY("munmap", SYS_munmap, target_munmap, 2, CALL_DIRECT, UINT /* PTR */, SIZE) /* 73 */ - ENTRY("mprotect", SYS_mprotect, mprotect, 3, CALL_DIRECT, PTR, SIZE, INT) /* 74 */ - ENTRY("madvise", SYS_madvise, madvise, 3, CALL_DIRECT, PTR, SIZE, INT) /* 75 */ - ENTRY("", 76, no_syscall, 0, CALL_INDIRECT, VOID) /* 76 old vhangup */ - ENTRY("", 77, no_syscall, 0, CALL_INDIRECT, VOID) /* 77 old vlimit */ - ENTRY("mincore", SYS_mincore, mincore, 3, CALL_DIRECT, PTR, SIZE, PTR) /* 78 */ - ENTRY("getgroups", SYS_getgroups, do_getgroups, 2, CALL_DIRECT, UINT, PTR) /* 79 */ - ENTRY("setgroups", SYS_setgroups, setgroups, 2, CALL_DIRECT, UINT, PTR) /* 80 */ - ENTRY("getpgrp", SYS_getpgrp, getpgrp, 0, CALL_DIRECT, VOID) /* 81 */ - ENTRY("setpgid", SYS_setpgid, setpgid, 2, CALL_DIRECT, INT, INT) /* 82 */ - ENTRY("setitimer", SYS_setitimer, setitimer, 3, CALL_DIRECT, INT, PTR, PTR) /* 83 */ - ENTRY("", 84, no_syscall, 0, CALL_INDIRECT, VOID) /* 84 old wait */ - ENTRY("swapon", SYS_swapon, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 85 */ - ENTRY("getitimer", SYS_getitimer, getitimer, 2, CALL_DIRECT, INT, PTR) /* 86 */ - ENTRY("", 87, no_syscall, 0, CALL_INDIRECT, VOID) /* 87 old gethostname */ - ENTRY("", 88, no_syscall, 0, CALL_INDIRECT, VOID) /* 88 old sethostname */ - ENTRY("getdtablesize", SYS_getdtablesize, getdtablesize, 0, CALL_DIRECT, VOID) /* 89 */ - ENTRY("dup2", SYS_dup2, dup2, 2, CALL_DIRECT, INT, INT) /* 90 */ - ENTRY("", 91, no_syscall, 0, CALL_INDIRECT, VOID) /* 91 old getdopt */ - ENTRY("fcntl", SYS_fcntl, do_fcntl, 3, CALL_DIRECT, INT, INT, INT) /* 92 */ - ENTRY("select", SYS_select, select, 5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR) /* 93 */ - ENTRY("", 94, no_syscall, 0, CALL_INDIRECT, VOID) /* 94 old setdopt */ - ENTRY("fsync", SYS_fsync, fsync, 1, CALL_DIRECT, INT) /* 95 */ - ENTRY("setpriority", SYS_setpriority, setpriority, 3, CALL_DIRECT, INT, INT, INT) /* 96 */ - ENTRY("socket", SYS_socket, socket, 3, CALL_DIRECT, INT, INT, INT) /* 97 */ - ENTRY("connect", SYS_connect, connect, 3, CALL_DIRECT, INT, PTR, INT) /* 98 */ - ENTRY("", 99, no_syscall, 0, CALL_INDIRECT, VOID) /* 99 old accept */ - ENTRY("getpriority", SYS_getpriority, getpriority, 2, CALL_DIRECT, INT, INT) /* 100 */ - ENTRY("", 101, no_syscall, 0, CALL_INDIRECT, VOID) /* 101 old send */ - ENTRY("", 102, no_syscall, 0, CALL_INDIRECT, VOID) /* 102 old recv */ - ENTRY("", 103, no_syscall, 0, CALL_INDIRECT, VOID) /* 103 old sigreturn */ - ENTRY("bind", SYS_bind, bind, 3, CALL_DIRECT, INT, PTR, INT) /* 104 */ - ENTRY("setsockopt", SYS_setsockopt, setsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, INT) /* 105 */ - ENTRY("listen", SYS_listen, listen, 2, CALL_DIRECT, INT, INT) /* 106 */ - ENTRY("", 107, no_syscall, 0, CALL_INDIRECT, VOID) /* 107 old vtimes */ - ENTRY("", 108, no_syscall, 0, CALL_INDIRECT, VOID) /* 108 old sigvec */ - ENTRY("", 109, no_syscall, 0, CALL_INDIRECT, VOID) /* 109 old sigblock */ - ENTRY("", 110, no_syscall, 0, CALL_INDIRECT, VOID) /* 110 old sigsetmask */ - ENTRY("sigsuspend", SYS_sigsuspend, unimpl_unix_syscall, 1, CALL_INDIRECT, INT) /* 111 */ - ENTRY("", 112, no_syscall, 0, CALL_INDIRECT, VOID) /* 112 old sigstack */ - ENTRY("", 113, no_syscall, 0, CALL_INDIRECT, VOID) /* 113 old recvmsg */ - ENTRY("", 114, no_syscall, 0, CALL_INDIRECT, VOID) /* 114 old sendmsg */ - ENTRY("", 115, no_syscall, 0, CALL_INDIRECT, VOID) /* 115 old vtrace */ - ENTRY("gettimeofday", SYS_gettimeofday, do_gettimeofday, 2, CALL_DIRECT, PTR, PTR) /* 116 */ - ENTRY("getrusage", SYS_getrusage, getrusage, 2, CALL_DIRECT, INT, PTR) /* 117 */ - ENTRY("getsockopt", SYS_getsockopt, getsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, PTR) /* 118 */ - ENTRY("", 119, no_syscall, 0, CALL_INDIRECT, VOID) /* 119 old resuba */ - ENTRY("readv", SYS_readv, do_readv, 3, CALL_DIRECT, INT, PTR, UINT) /* 120 */ - ENTRY("writev", SYS_writev, do_writev, 3, CALL_DIRECT, INT, PTR, UINT) /* 121 */ - ENTRY("settimeofday", SYS_settimeofday, settimeofday, 2, CALL_DIRECT, PTR, PTR) /* 122 */ - ENTRY("fchown", SYS_fchown, fchown, 3, CALL_DIRECT, INT, INT, INT) /* 123 */ - ENTRY("fchmod", SYS_fchmod, fchmod, 2, CALL_DIRECT, INT, INT) /* 124 */ - ENTRY("", 125, no_syscall, 0, CALL_INDIRECT, VOID) /* 125 old recvfrom */ - ENTRY("", 126, no_syscall, 0, CALL_INDIRECT, VOID) /* 126 old setreuid */ - ENTRY("", 127, no_syscall, 0, CALL_INDIRECT, VOID) /* 127 old setregid */ - ENTRY("rename", SYS_rename, rename, 2, CALL_DIRECT, PTR, PTR) /* 128 */ - ENTRY("", 129, no_syscall, 0, CALL_INDIRECT, VOID) /* 129 old truncate */ - ENTRY("", 130, no_syscall, 0, CALL_INDIRECT, VOID) /* 130 old ftruncate */ - ENTRY("flock", SYS_flock, flock, 2, CALL_DIRECT, INT, INT) /* 131 */ - ENTRY("mkfifo", SYS_mkfifo, mkfifo, 2, CALL_DIRECT, PTR, INT) /* 132 */ - ENTRY("sendto", SYS_sendto, sendto, 6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT) /* 133 */ - ENTRY("shutdown", SYS_shutdown, shutdown, 2, CALL_DIRECT, INT, INT) /* 134 */ - ENTRY("socketpair", SYS_socketpair, socketpair, 4, CALL_DIRECT, INT, INT, INT, PTR) /* 135 */ - ENTRY("mkdir", SYS_mkdir, mkdir, 2, CALL_DIRECT, PTR, INT) /* 136 */ - ENTRY("rmdir", SYS_rmdir, rmdir, 1, CALL_DIRECT, PTR) /* 137 */ - ENTRY("utimes", SYS_utimes, do_utimes, 2, CALL_DIRECT, PTR, PTR) /* 138 */ - ENTRY("futimes", SYS_futimes, do_futimes, 2, CALL_DIRECT, INT, PTR) /* 139 */ - ENTRY("adjtime", SYS_adjtime, adjtime, 2, CALL_DIRECT, PTR, PTR) /* 140 */ - ENTRY("", 141, no_syscall, 0, CALL_INDIRECT, VOID) /* 141 old getpeername */ - ENTRY("", 142, no_syscall, 0, CALL_INDIRECT, VOID) /* 142 old gethostid */ - ENTRY("", 143, no_syscall, 0, CALL_INDIRECT, VOID) /* 143 old sethostid */ - ENTRY("", 144, no_syscall, 0, CALL_INDIRECT, VOID) /* 144 old getrlimit */ - ENTRY("", 145, no_syscall, 0, CALL_INDIRECT, VOID) /* 145 old setrlimit */ - ENTRY("", 146, no_syscall, 0, CALL_INDIRECT, VOID) /* 146 old killpg */ - ENTRY("setsid", SYS_setsid, setsid, 0, CALL_DIRECT, VOID) /* 147 */ - ENTRY("", 148, no_syscall, 0, CALL_INDIRECT, VOID) /* 148 old setquota */ - ENTRY("", 149, no_syscall, 0, CALL_INDIRECT, VOID) /* 149 old qquota */ - ENTRY("", 150, no_syscall, 0, CALL_INDIRECT, VOID) /* 150 old getsockname */ - ENTRY("getpgid", SYS_getpgid, getpgid, 1, CALL_DIRECT, INT) /* 151 */ - ENTRY("setprivexec", SYS_setprivexec, no_syscall, 1, CALL_INDIRECT, VOID) /* 152 */ - ENTRY("pread", SYS_pread, do_pread, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 153 */ - ENTRY("pwrite", SYS_pwrite, pwrite, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 154 */ -#ifdef SYS_nfssvc - ENTRY("nfssvc", SYS_nfssvc, nfssvc, 2, CALL_DIRECT, INT, PTR) /* 155 */ -#else - ENTRY("nfssvc", 155, no_syscall, 2, CALL_INDIRECT, VOID) /* 155 */ -#endif - ENTRY("", 155, no_syscall, 0, CALL_INDIRECT, VOID) /* 155 */ - ENTRY("", 156, no_syscall, 0, CALL_INDIRECT, VOID) /* 156 old getdirentries */ - ENTRY("statfs", SYS_statfs, do_statfs, 2, CALL_DIRECT, PTR, PTR) /* 157 */ - ENTRY("fstatfs", SYS_fstatfs, do_fstatfs, 2, CALL_DIRECT, INT, PTR) /* 158 */ - ENTRY("unmount", SYS_unmount, unmount, 2, CALL_DIRECT, PTR, INT) /* 159 */ - ENTRY("", 160, no_syscall, 0, CALL_INDIRECT, VOID) /* 160 old async_daemon */ - ENTRY("", 161, no_syscall, 0, CALL_INDIRECT, VOID) /* 161 */ - ENTRY("", 162, no_syscall, 0, CALL_INDIRECT, VOID) /* 162 old getdomainname */ - ENTRY("", 163, no_syscall, 0, CALL_INDIRECT, VOID) /* 163 old setdomainname */ - ENTRY("", 164, no_syscall, 0, CALL_INDIRECT, VOID) /* 164 */ - ENTRY("quotactl", SYS_quotactl, no_syscall, 4, CALL_INDIRECT, VOID) /* 165 */ - ENTRY("", 166, no_syscall, 0, CALL_INDIRECT, VOID) /* 166 old exportfs */ - ENTRY("mount", SYS_mount, mount, 4, CALL_DIRECT, PTR, PTR, INT, PTR) /* 167 */ - ENTRY("", 168, no_syscall, 0, CALL_INDIRECT, VOID) /* 168 old ustat */ - ENTRY("", 169, no_syscall, 0, CALL_INDIRECT, VOID) /* 169 */ - ENTRY("table", SYS_table, no_syscall, 0, CALL_INDIRECT, VOID) /* 170 old table */ - ENTRY("", 171, no_syscall, 0, CALL_INDIRECT, VOID) /* 171 old wait3 */ - ENTRY("", 172, no_syscall, 0, CALL_INDIRECT, VOID) /* 172 old rpause */ - ENTRY("waitid", SYS_waitid, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 173 */ - ENTRY("", 174, no_syscall, 0, CALL_INDIRECT, VOID) /* 174 old getdents */ - ENTRY("", 175, no_syscall, 0, CALL_INDIRECT, VOID) /* 175 old gc_control */ - ENTRY("add_profil", SYS_add_profil, add_profil, 4, CALL_DIRECT, PTR, SIZE, UINT, UINT) /* 176 */ - ENTRY("", 177, no_syscall, 0, CALL_INDIRECT, VOID) /* 177 */ - ENTRY("", 178, no_syscall, 0, CALL_INDIRECT, VOID) /* 178 */ - ENTRY("", 179, no_syscall, 0, CALL_INDIRECT, VOID) /* 179 */ - ENTRY("kdebug_trace", SYS_kdebug_trace, no_syscall, 6, CALL_INDIRECT, VOID) /* 180 */ - ENTRY("setgid", SYS_setgid, setgid, 1, CALL_DIRECT, INT) /* 181 */ - ENTRY("setegid", SYS_setegid, setegid, 1, CALL_DIRECT, INT) /* 182 */ - ENTRY("seteuid", SYS_seteuid, seteuid, 1, CALL_DIRECT, INT) /* 183 */ - ENTRY("sigreturn", SYS_sigreturn, do_sigreturn, 2, CALL_INDIRECT, PTR, INT) /* 184 */ - ENTRY("chud", SYS_chud, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 185 */ - ENTRY("", 186, no_syscall, 0, CALL_INDIRECT, VOID) /* 186 */ - ENTRY("", 187, no_syscall, 0, CALL_INDIRECT, VOID) /* 187 */ - ENTRY("stat", SYS_stat, do_stat, 2, CALL_DIRECT, PTR, PTR) /* 188 */ - ENTRY("fstat", SYS_fstat, do_fstat, 2, CALL_DIRECT, INT, PTR) /* 189 */ - ENTRY("lstat", SYS_lstat, do_lstat, 2, CALL_DIRECT, PTR, PTR) /* 190 */ - ENTRY("pathconf", SYS_pathconf, pathconf, 2, CALL_DIRECT, PTR, INT) /* 191 */ - ENTRY("fpathconf", SYS_fpathconf, fpathconf, 2, CALL_DIRECT, INT, INT) /* 192 */ - ENTRY("getfsstat", SYS_getfsstat, do_getfsstat, 3, CALL_DIRECT, PTR, INT, INT) /* 193 */ - ENTRY("", 193, no_syscall, 0, CALL_INDIRECT, VOID) /* 193 */ - ENTRY("getrlimit", SYS_getrlimit, getrlimit, 2, CALL_DIRECT, UINT, PTR) /* 194 */ - ENTRY("setrlimit", SYS_setrlimit, setrlimit, 2, CALL_DIRECT, UINT, PTR) /* 195 */ - ENTRY("getdirentries", SYS_getdirentries, do_getdirentries, 4, CALL_DIRECT, INT, PTR, UINT, PTR) /* 196 */ - ENTRY("mmap", SYS_mmap, target_mmap, 6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET) /* 197 */ - ENTRY("", 198, no_syscall, 0, CALL_INDIRECT, VOID) /* 198 __syscall */ - ENTRY("lseek", SYS_lseek, do_lseek, 3, CALL_INDIRECT, INT, OFFSET, INT) /* 199 */ - ENTRY("truncate", SYS_truncate, truncate, 2, CALL_DIRECT, PTR, OFFSET) /* 200 */ - ENTRY("ftruncate", SYS_ftruncate, ftruncate, 2, CALL_DIRECT, INT, OFFSET) /* 201 */ - ENTRY("__sysctl", SYS___sysctl, do___sysctl, 6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE) /* 202 */ - ENTRY("mlock", SYS_mlock, mlock, 2, CALL_DIRECT, PTR, SIZE) /* 203 */ - ENTRY("munlock", SYS_munlock, munlock, 2, CALL_DIRECT, PTR, SIZE) /* 204 */ - ENTRY("undelete", SYS_undelete, undelete, 1, CALL_DIRECT, PTR) /* 205 */ - ENTRY("ATsocket", SYS_ATsocket, no_syscall, 1, CALL_INDIRECT, VOID) /* 206 */ - ENTRY("ATgetmsg", SYS_ATgetmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 207 */ - ENTRY("ATputmsg", SYS_ATputmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 208 */ - ENTRY("ATPsndreq", SYS_ATPsndreq, no_syscall, 4, CALL_INDIRECT, VOID) /* 209 */ - ENTRY("ATPsndrsp", SYS_ATPsndrsp, no_syscall, 4, CALL_INDIRECT, VOID) /* 210 */ - ENTRY("ATPgetreq", SYS_ATPgetreq, no_syscall, 3, CALL_INDIRECT, VOID) /* 211 */ - ENTRY("ATPgetrsp", SYS_ATPgetrsp, no_syscall, 2, CALL_INDIRECT, VOID) /* 212 */ - ENTRY("", 213, no_syscall, 0, CALL_INDIRECT, VOID) /* 213 Reserved for AppleTalk */ - ENTRY("kqueue_from_portset_np", SYS_kqueue_from_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 214 */ - ENTRY("kqueue_portset_np", SYS_kqueue_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 215 */ - ENTRY("mkcomplex", SYS_mkcomplex, no_syscall, 3, CALL_INDIRECT, VOID) /* 216 soon to be obsolete */ - ENTRY("statv", SYS_statv, no_syscall, 2, CALL_INDIRECT, VOID) /* 217 soon to be obsolete */ - ENTRY("lstatv", SYS_lstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 218 soon to be obsolete */ - ENTRY("fstatv", SYS_fstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 219 soon to be obsolete */ - ENTRY("getattrlist", SYS_getattrlist, do_getattrlist, 5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT) /* 220 */ - ENTRY("setattrlist", SYS_setattrlist, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 221 */ - ENTRY("getdirentriesattr", SYS_getdirentriesattr, do_getdirentriesattr, 8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT) /* 222 */ - ENTRY("exchangedata", SYS_exchangedata, exchangedata, 3, CALL_DIRECT, PTR, PTR, UINT) /* 223 */ - ENTRY("checkuseraccess", SYS_checkuseraccess, checkuseraccess, 6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT) /* 224 */ - ENTRY("", 224, no_syscall, 0, CALL_INDIRECT, VOID) /* 224 HFS checkuseraccess check access to a file */ - ENTRY("searchfs", SYS_searchfs, searchfs, 6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR) /* 225 */ - ENTRY("delete", SYS_delete, no_syscall, 1, CALL_INDIRECT, VOID) /* 226 private delete ( Carbon semantics ) */ - ENTRY("copyfile", SYS_copyfile, no_syscall, 4, CALL_INDIRECT, VOID) /* 227 */ - ENTRY("", 228, no_syscall, 0, CALL_INDIRECT, VOID) /* 228 */ - ENTRY("", 229, no_syscall, 0, CALL_INDIRECT, VOID) /* 229 */ - ENTRY("poll", SYS_poll, no_syscall, 3, CALL_INDIRECT, VOID) /* 230 */ - ENTRY("watchevent", SYS_watchevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 231 */ - ENTRY("waitevent", SYS_waitevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 232 */ - ENTRY("modwatch", SYS_modwatch, no_syscall, 2, CALL_INDIRECT, VOID) /* 233 */ - ENTRY("getxattr", SYS_getxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 234 */ - ENTRY("fgetxattr", SYS_fgetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 235 */ - ENTRY("setxattr", SYS_setxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 236 */ - ENTRY("fsetxattr", SYS_fsetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 237 */ - ENTRY("removexattr", SYS_removexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 238 */ - ENTRY("fremovexattr", SYS_fremovexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 239 */ - ENTRY("listxattr", SYS_listxattr, listxattr, 4, CALL_INDIRECT, VOID) /* 240 */ - ENTRY("flistxattr", SYS_flistxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 241 */ - ENTRY("fsctl", SYS_fsctl, fsctl, 4, CALL_DIRECT, PTR, UINT, PTR, UINT) /* 242 */ - ENTRY("initgroups", SYS_initgroups, unimpl_unix_syscall, 3, CALL_INDIRECT, UINT, PTR, INT) /* 243 */ - ENTRY("", 244, no_syscall, 0, CALL_INDIRECT, VOID) /* 244 */ - ENTRY("", 245, no_syscall, 0, CALL_INDIRECT, VOID) /* 245 */ - ENTRY("", 246, no_syscall, 0, CALL_INDIRECT, VOID) /* 246 */ -#ifdef SYS_nfsclnt - ENTRY("nfsclnt", SYS_nfsclnt, nfsclnt, 2, CALL_DIRECT, INT, PTR) /* 247 */ -#else - ENTRY("nfsclnt", 247, no_syscall, 2, CALL_INDIRECT, VOID) /* 247 */ -#endif - ENTRY("", 247, no_syscall, 0, CALL_INDIRECT, VOID) /* 247 */ - ENTRY("", 248, no_syscall, 0, CALL_INDIRECT, VOID) /* 248 */ - ENTRY("", 249, no_syscall, 0, CALL_INDIRECT, VOID) /* 249 */ - ENTRY("minherit", SYS_minherit, minherit, 3, CALL_DIRECT, PTR, INT, INT) /* 250 */ - ENTRY("semsys", SYS_semsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 251 */ - ENTRY("msgsys", SYS_msgsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 252 */ - ENTRY("shmsys", SYS_shmsys, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 253 */ - ENTRY("semctl", SYS_semctl, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 254 */ - ENTRY("semget", SYS_semget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 255 */ - ENTRY("semop", SYS_semop, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 256 */ - ENTRY("", 257, no_syscall, 0, CALL_INDIRECT, VOID) /* 257 */ - ENTRY("msgctl", SYS_msgctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 258 */ - ENTRY("msgget", SYS_msgget, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 259 */ - ENTRY("msgsnd", SYS_msgsnd, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 260 */ - ENTRY("msgrcv", SYS_msgrcv, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 261 */ - ENTRY("shmat", SYS_shmat, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 262 */ - ENTRY("shmctl", SYS_shmctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 263 */ - ENTRY("shmdt", SYS_shmdt, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 264 */ - ENTRY("shmget", SYS_shmget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 265 */ - ENTRY("shm_open", SYS_shm_open, shm_open, 3, CALL_DIRECT, PTR, INT, INT) /* 266 */ - ENTRY("shm_unlink", SYS_shm_unlink, shm_unlink, 1, CALL_DIRECT, PTR) /* 267 */ - ENTRY("sem_open", SYS_sem_open, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 268 */ - ENTRY("sem_close", SYS_sem_close, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 269 */ - ENTRY("sem_unlink", SYS_sem_unlink, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 270 */ - ENTRY("sem_wait", SYS_sem_wait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 271 */ - ENTRY("sem_trywait", SYS_sem_trywait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 272 */ - ENTRY("sem_post", SYS_sem_post, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 273 */ - ENTRY("sem_getvalue", SYS_sem_getvalue, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 274 */ - ENTRY("sem_init", SYS_sem_init, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 275 */ - ENTRY("sem_destroy", SYS_sem_destroy, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 276 */ - ENTRY("open_extended", SYS_open_extended, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 277 */ - ENTRY("umask_extended", SYS_umask_extended, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 278 */ - ENTRY("stat_extended", SYS_stat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 279 */ - ENTRY("lstat_extended", SYS_lstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 280 */ - ENTRY("fstat_extended", SYS_fstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 281 */ - ENTRY("chmod_extended", SYS_chmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 282 */ - ENTRY("fchmod_extended", SYS_fchmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 283 */ - ENTRY("access_extended", SYS_access_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 284 */ - ENTRY("settid", SYS_settid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 285 */ - ENTRY("gettid", SYS_gettid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 286 */ - ENTRY("setsgroups", SYS_setsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 287 */ - ENTRY("getsgroups", SYS_getsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 288 */ - ENTRY("setwgroups", SYS_setwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 289 */ - ENTRY("getwgroups", SYS_getwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 290 */ - ENTRY("mkfifo_extended", SYS_mkfifo_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 291 */ - ENTRY("mkdir_extended", SYS_mkdir_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 292 */ - ENTRY("identitysvc", SYS_identitysvc, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 293 */ - ENTRY("", 294, no_syscall, 0, CALL_INDIRECT, VOID) /* 294 */ - ENTRY("", 295, no_syscall, 0, CALL_INDIRECT, VOID) /* 295 */ - ENTRY("load_shared_file", SYS_load_shared_file, unimpl_unix_syscall, 7, CALL_INDIRECT, VOID) /* 296 */ - ENTRY("reset_shared_file", SYS_reset_shared_file, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 297 */ - ENTRY("new_system_shared_regions", SYS_new_system_shared_regions, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 298 */ - ENTRY("shared_region_map_file_np", SYS_shared_region_map_file_np, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 299 */ - ENTRY("shared_region_make_private_np", SYS_shared_region_make_private_np, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 300 */ - ENTRY("", 301, no_syscall, 0, CALL_INDIRECT, VOID) /* 301 */ - ENTRY("", 302, no_syscall, 0, CALL_INDIRECT, VOID) /* 302 */ - ENTRY("", 303, no_syscall, 0, CALL_INDIRECT, VOID) /* 303 */ - ENTRY("", 304, no_syscall, 0, CALL_INDIRECT, VOID) /* 304 */ - ENTRY("", 305, no_syscall, 0, CALL_INDIRECT, VOID) /* 305 */ - ENTRY("", 306, no_syscall, 0, CALL_INDIRECT, VOID) /* 306 */ - ENTRY("", 307, no_syscall, 0, CALL_INDIRECT, VOID) /* 307 */ - ENTRY("", 308, no_syscall, 0, CALL_INDIRECT, VOID) /* 308 */ - ENTRY("", 309, no_syscall, 0, CALL_INDIRECT, VOID) /* 309 */ - ENTRY("getsid", SYS_getsid, getsid, 1, CALL_DIRECT, INT) /* 310 */ - ENTRY("settid_with_pid", SYS_settid_with_pid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 311 */ - ENTRY("", 312, no_syscall, 0, CALL_INDIRECT, VOID) /* 312 */ - ENTRY("aio_fsync", SYS_aio_fsync, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 313 */ - ENTRY("aio_return", SYS_aio_return, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 314 */ - ENTRY("aio_suspend", SYS_aio_suspend, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 315 */ - ENTRY("aio_cancel", SYS_aio_cancel, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 316 */ - ENTRY("aio_error", SYS_aio_error, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 317 */ - ENTRY("aio_read", SYS_aio_read, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 318 */ - ENTRY("aio_write", SYS_aio_write, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 319 */ - ENTRY("lio_listio", SYS_lio_listio, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 320 */ - ENTRY("", 321, no_syscall, 0, CALL_INDIRECT, VOID) /* 321 */ - ENTRY("", 322, no_syscall, 0, CALL_INDIRECT, VOID) /* 322 */ - ENTRY("", 323, no_syscall, 0, CALL_INDIRECT, VOID) /* 323 */ - ENTRY("mlockall", SYS_mlockall, mlockall, 1, CALL_DIRECT, INT) /* 324 */ - ENTRY("munlockall", SYS_munlockall, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 325 */ - ENTRY("", 326, no_syscall, 0, CALL_INDIRECT, VOID) /* 326 */ - ENTRY("issetugid", SYS_issetugid, issetugid, 0, CALL_DIRECT, VOID) /* 327 */ - ENTRY("__pthread_kill", SYS___pthread_kill, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 328 */ - ENTRY("pthread_sigmask", SYS_pthread_sigmask, pthread_sigmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 329 */ - ENTRY("sigwait", SYS_sigwait, sigwait, 2, CALL_DIRECT, PTR, PTR) /* 330 */ - ENTRY("__disable_threadsignal", SYS___disable_threadsignal, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 331 */ - ENTRY("__pthread_markcancel", SYS___pthread_markcancel, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 332 */ - ENTRY("__pthread_canceled", SYS___pthread_canceled, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 333 */ - ENTRY("__semwait_signal", SYS___semwait_signal, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 334 */ - ENTRY("utrace", SYS_utrace, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 335 */ - ENTRY("proc_info", SYS_proc_info, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 336 */ - ENTRY("", 337, no_syscall, 0, CALL_INDIRECT, VOID) /* 337 */ - ENTRY("", 338, no_syscall, 0, CALL_INDIRECT, VOID) /* 338 */ - ENTRY("", 339, no_syscall, 0, CALL_INDIRECT, VOID) /* 339 */ - ENTRY("", 340, no_syscall, 0, CALL_INDIRECT, VOID) /* 340 */ - ENTRY("", 341, no_syscall, 0, CALL_INDIRECT, VOID) /* 341 */ - ENTRY("", 342, no_syscall, 0, CALL_INDIRECT, VOID) /* 342 */ - ENTRY("", 343, no_syscall, 0, CALL_INDIRECT, VOID) /* 343 */ - ENTRY("", 344, no_syscall, 0, CALL_INDIRECT, VOID) /* 344 */ - ENTRY("", 345, no_syscall, 0, CALL_INDIRECT, VOID) /* 345 */ - ENTRY("", 346, no_syscall, 0, CALL_INDIRECT, VOID) /* 346 */ - ENTRY("", 347, no_syscall, 0, CALL_INDIRECT, VOID) /* 347 */ - ENTRY("", 348, no_syscall, 0, CALL_INDIRECT, VOID) /* 348 */ - ENTRY("", 349, no_syscall, 0, CALL_INDIRECT, VOID) /* 349 */ - ENTRY("audit", SYS_audit, audit, 2, CALL_DIRECT, PTR, INT) /* 350 */ - ENTRY("auditon", SYS_auditon, auditon, 3, CALL_DIRECT, INT, PTR, INT) /* 351 */ - ENTRY("", 352, no_syscall, 0, CALL_INDIRECT, VOID) /* 352 */ - ENTRY("getauid", SYS_getauid, getauid, 1, CALL_DIRECT, PTR) /* 353 */ - ENTRY("setauid", SYS_setauid, setauid, 1, CALL_DIRECT, PTR) /* 354 */ - ENTRY("getaudit", SYS_getaudit, getaudit, 1, CALL_DIRECT, PTR) /* 355 */ - ENTRY("setaudit", SYS_setaudit, setaudit, 1, CALL_DIRECT, PTR) /* 356 */ - ENTRY("getaudit_addr", SYS_getaudit_addr, getaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 357 */ - ENTRY("setaudit_addr", SYS_setaudit_addr, setaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 358 */ - ENTRY("auditctl", SYS_auditctl, auditctl, 1, CALL_DIRECT, PTR) /* 359 */ - ENTRY("", 360, no_syscall, 0, CALL_INDIRECT, VOID) /* 360 */ - ENTRY("", 361, no_syscall, 0, CALL_INDIRECT, VOID) /* 361 */ - ENTRY("kqueue", SYS_kqueue, kqueue, 0, CALL_DIRECT, VOID) /* 362 */ - ENTRY("kevent", SYS_kevent, kevent, 6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR) /* 363 */ - ENTRY("lchown", SYS_lchown, lchown, 3, CALL_DIRECT, PTR, INT , INT) /* 364 */ - ENTRY("stack_snapshot", SYS_stack_snapshot, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 365 */ - ENTRY("", 366, no_syscall, 0, CALL_INDIRECT, VOID) /* 366 */ - ENTRY("", 367, no_syscall, 0, CALL_INDIRECT, VOID) /* 367 */ - ENTRY("", 368, no_syscall, 0, CALL_INDIRECT, VOID) /* 368 */ - ENTRY("", 369, no_syscall, 0, CALL_INDIRECT, VOID) /* 369 */ diff --git a/default-configs/i386-darwin-user.mak b/default-configs/i386-darwin-user.mak deleted file mode 100644 index 19afd3dae5..0000000000 --- a/default-configs/i386-darwin-user.mak +++ /dev/null @@ -1 +0,0 @@ -# Default configuration for i386-darwin-user diff --git a/default-configs/ppc-darwin-user.mak b/default-configs/ppc-darwin-user.mak deleted file mode 100644 index 153ed12876..0000000000 --- a/default-configs/ppc-darwin-user.mak +++ /dev/null @@ -1,3 +0,0 @@ -# Default configuration for ppc-darwin-user - -CONFIG_GDBSTUB_XML=y diff --git a/qemu-doc.texi b/qemu-doc.texi index 9e07ba6c1b..e5d7ac41ab 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2270,7 +2270,6 @@ so should only be used with trusted guest OS. @menu * Supported Operating Systems :: * Linux User space emulator:: -* Mac OS X/Darwin User space emulator :: * BSD User space emulator :: @end menu @@ -2283,8 +2282,6 @@ The following OS are supported in user space emulation: @item Linux (referred as qemu-linux-user) @item -Mac OS X/Darwin (referred as qemu-darwin-user) -@item BSD (referred as qemu-bsd-user) @end itemize @@ -2489,93 +2486,6 @@ The binary format is detected automatically. @command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI). -@node Mac OS X/Darwin User space emulator -@section Mac OS X/Darwin User space emulator - -@menu -* Mac OS X/Darwin Status:: -* Mac OS X/Darwin Quick Start:: -* Mac OS X/Darwin Command line options:: -@end menu - -@node Mac OS X/Darwin Status -@subsection Mac OS X/Darwin Status - -@itemize @minus -@item -target x86 on x86: Most apps (Cocoa and Carbon too) works. [1] -@item -target PowerPC on x86: Not working as the ppc commpage can't be mapped (yet!) -@item -target PowerPC on PowerPC: Most apps (Cocoa and Carbon too) works. [1] -@item -target x86 on PowerPC: most utilities work. Cocoa and Carbon apps are not yet supported. -@end itemize - -[1] If you're host commpage can be executed by qemu. - -@node Mac OS X/Darwin Quick Start -@subsection Quick Start - -In order to launch a Mac OS X/Darwin process, QEMU needs the process executable -itself and all the target dynamic libraries used by it. If you don't have the FAT -libraries (you're running Mac OS X/ppc) you'll need to obtain it from a Mac OS X -CD or compile them by hand. - -@itemize - -@item On x86, you can just try to launch any process by using the native -libraries: - -@example -qemu-i386 /bin/ls -@end example - -or to run the ppc version of the executable: - -@example -qemu-ppc /bin/ls -@end example - -@item On ppc, you'll have to tell qemu where your x86 libraries (and dynamic linker) -are installed: - -@example -qemu-i386 -L /opt/x86_root/ /bin/ls -@end example - -@code{-L /opt/x86_root/} tells that the dynamic linker (dyld) path is in -@file{/opt/x86_root/usr/bin/dyld}. - -@end itemize - -@node Mac OS X/Darwin Command line options -@subsection Command line options - -@example -usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...] -@end example - -@table @option -@item -h -Print the help -@item -L path -Set the library root path (default=/) -@item -s size -Set the stack size in bytes (default=524288) -@end table - -Debug options: - -@table @option -@item -d -Activate log (logfile=/tmp/qemu.log) -@item -p pagesize -Act as if the host page size was 'pagesize' bytes -@item -singlestep -Run the emulation in single step mode. -@end table - @node BSD User space emulator @section BSD User space emulator diff --git a/qemu-tech.texi b/qemu-tech.texi index 5676fb7afd..b51a58abba 100644 --- a/qemu-tech.texi +++ b/qemu-tech.texi @@ -112,8 +112,7 @@ QEMU user mode emulation features: @end itemize Linux user emulator (Linux host only) can be used to launch the Wine -Windows API emulator (@url{http://www.winehq.org}). A Darwin user -emulator (Darwin hosts only) exists and a BSD user emulator for BSD +Windows API emulator (@url{http://www.winehq.org}). A BSD user emulator for BSD hosts is under development. It would also be possible to develop a similar user emulator for Solaris. |