]> git.proxmox.com Git - qemu.git/commitdiff
Darwin userspace emulation, by Pierre d'Herbemont.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 18 Jan 2007 20:06:33 +0000 (20:06 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 18 Jan 2007 20:06:33 +0000 (20:06 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2332 c046a42c-6fe2-441c-8c8c-71466251a162

13 files changed:
Makefile.target
configure
darwin-user/commpage.c [new file with mode: 0644]
darwin-user/ioctls.h [new file with mode: 0644]
darwin-user/ioctls_types.h [new file with mode: 0644]
darwin-user/machload.c [new file with mode: 0644]
darwin-user/main.c [new file with mode: 0644]
darwin-user/mmap.c [new file with mode: 0644]
darwin-user/qemu.h [new file with mode: 0644]
darwin-user/signal.c [new file with mode: 0644]
darwin-user/syscall.c [new file with mode: 0644]
darwin-user/syscalls.h [new file with mode: 0644]
gdbstub.c

index 5973211c39e4f96af402d64b519180d0a6bf2442..af4a69a6e20ddf12841604f495a4efbc66b2bca6 100644 (file)
@@ -13,7 +13,11 @@ endif
 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
 CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
-ifdef CONFIG_USER_ONLY
+ifdef CONFIG_DARWIN_USER
+VPATH+=:$(SRC_PATH)/darwin-user
+CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
+endif
+ifdef CONFIG_LINUX_USER
 VPATH+=:$(SRC_PATH)/linux-user
 CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
@@ -85,12 +89,14 @@ endif
 ifdef USE_I386_LD
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 else
+ifdef CONFIG_LINUX_USER
 # WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
 # that the kernel ELF loader considers as an executable. I think this
 # is the simplest way to make it self virtualizable!
 BASE_LDFLAGS+=-Wl,-shared
 endif
 endif
+endif
 
 ifeq ($(ARCH),x86_64)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
@@ -98,8 +104,10 @@ endif
 
 ifeq ($(ARCH),ppc)
 CPPFLAGS+= -D__powerpc__
+ifdef CONFIG_LINUX_USER
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
 endif
+endif
 
 ifeq ($(ARCH),s390)
 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
@@ -186,6 +194,7 @@ BASE_LDFLAGS+=-p
 main.o: BASE_CFLAGS+=-p
 endif
 
+ifdef CONFIG_LINUX_USER
 OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
       elfload.o linuxload.o
 ifdef TARGET_HAS_BFLT
@@ -203,6 +212,12 @@ endif
 ifeq ($(TARGET_ARCH), m68k)
 OBJS+= m68k-sim.o m68k-semi.o
 endif
+endif #CONFIG_LINUX_USER
+
+ifdef CONFIG_DARWIN_USER
+OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
+endif
+
 SRCS:= $(OBJS:.o=.c)
 OBJS+= libqemu.a
 
index 68c3fcc7b679293b50b338aa33d137d652677f2a..eda1437fe8acf68a7484dbcf1dc1ab8826db15a0 100755 (executable)
--- a/configure
+++ b/configure
@@ -94,7 +94,8 @@ cocoa="no"
 check_gfx="yes"
 check_gcc="yes"
 softmmu="yes"
-user="no"
+linux_user="no"
+darwin_user="no"
 build_docs="no"
 uname_release=""
 
@@ -126,6 +127,7 @@ oss="yes"
 Darwin)
 bsd="yes"
 darwin="yes"
+darwin_user="yes"
 OS_CFLAGS="-mdynamic-no-pic"
 ;;
 SunOS)
@@ -134,7 +136,7 @@ solaris="yes"
 *)
 oss="yes"
 linux="yes"
-user="yes"
+linux_user="yes"
 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     kqemu="yes"
 fi
@@ -240,9 +242,13 @@ for opt do
   ;;
   --enable-system) softmmu="yes"
   ;;
-  --disable-user) user="no"
+  --disable-linux-user) linux_user="no"
   ;;
-  --enable-user) user="yes"
+  --enable-linux-user) linux_user="yes"
+  ;;
+  --disable-darwin-user) darwin_user="no"
+  ;;
+  --enable-darwin-user) darwin_user="yes"
   ;;
   --enable-uname-release=*) uname_release="$optarg"
   ;;
@@ -287,8 +293,10 @@ echo "  --enable-fmod            enable FMOD audio driver"
 echo "  --enabled-dsound         enable DirectSound audio driver"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
-echo "  --enable-user            enable all linux usermode emulation targets"
-echo "  --disable-user           disable all linux usermode 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 "  --fmod-lib               path to FMOD library"
 echo "  --fmod-inc               path to FMOD includes"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
@@ -408,8 +416,12 @@ if test -z "$target_list" ; then
         target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
     fi
 # the following are Linux specific
-    if [ "$user" = "yes" ] ; then
-        target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user m68k-user $target_list"
+    if [ "$linux_user" = "yes" ] ; then
+        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user $target_list"
+    fi
+# the following are Darwin specific
+    if [ "$darwin_user" = "yes" ] ; then
+        target_list="i386-darwin-user ppc-darwin-user $target_list"
     fi
 else
     target_list=`echo "$target_list" | sed -e 's/,/ /g'`
@@ -787,6 +799,16 @@ if expr $target : '.*-user' > /dev/null ; then
   target_user_only="yes"
 fi
 
+target_linux_user="no"
+if expr $target : '.*-linux-user' > /dev/null ; then
+  target_linux_user="yes"
+fi
+
+target_darwin_user="no"
+if expr $target : '.*-darwin-user' > /dev/null ; then
+  target_darwin_user="yes"
+fi
+
 if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
         -a "$sdl" = "no" -a "$cocoa" = "no" ; then
     echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
@@ -799,7 +821,7 @@ fi
 
 mkdir -p $target_dir
 mkdir -p $target_dir/fpu
-if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
+if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
   mkdir -p $target_dir/nwfpe
 fi
 if test "$target_user_only" = "no" ; then
@@ -894,6 +916,14 @@ if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=yes" >> $config_mak
   echo "#define CONFIG_USER_ONLY 1" >> $config_h
 fi
+if test "$target_linux_user" = "yes" ; then
+  echo "CONFIG_LINUX_USER=yes" >> $config_mak
+  echo "#define CONFIG_LINUX_USER 1" >> $config_h
+fi
+if test "$target_darwin_user" = "yes" ; then
+  echo "CONFIG_DARWIN_USER=yes" >> $config_mak
+  echo "#define CONFIG_DARWIN_USER 1" >> $config_h
+fi
 
 if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
   echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
diff --git a/darwin-user/commpage.c b/darwin-user/commpage.c
new file mode 100644 (file)
index 0000000..12ee1da
--- /dev/null
@@ -0,0 +1,358 @@
+ /*
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/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 { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __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, 0x2c0,  do_cgettimeofday,      CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_dcache_flush,      0, 0x2c0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x2c0,  unimpl_commpage,       CALL_INDIRECT),
+    COMMPAGE_ENTRY(pthread_self,          0, 0x2c0,  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(__powerpc__) ^ 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 < sizeof(commpage_entries)/sizeof(commpage_entries[0]); 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(value && 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(%llx,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)
+{
+    gemu_log("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 < sizeof(commpage_entries)/sizeof(commpage_entries[0]); 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
new file mode 100644 (file)
index 0000000..dc73af2
--- /dev/null
@@ -0,0 +1,4 @@
+     /* 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
new file mode 100644 (file)
index 0000000..63e65f0
--- /dev/null
@@ -0,0 +1 @@
+STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
\ No newline at end of file
diff --git a/darwin-user/machload.c b/darwin-user/machload.c
new file mode 100644 (file)
index 0000000..3ba417e
--- /dev/null
@@ -0,0 +1,903 @@
+/*
+ *  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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#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 { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
+#else
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __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);
+void qerror(const char *format, ...);
+#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 whith -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: unkown 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 choosen 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
new file mode 100644 (file)
index 0000000..259aab3
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#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"
+
+#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>
+
+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);
+}
+
+void cpu_outb(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
+}
+
+void cpu_outw(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
+}
+
+void cpu_outl(CPUState *env, int addr, int val)
+{
+    fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
+}
+
+int cpu_inb(CPUState *env, int addr)
+{
+    fprintf(stderr, "inb: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inw(CPUState *env, int addr)
+{
+    fprintf(stderr, "inw: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_inl(CPUState *env, int addr)
+{
+    fprintf(stderr, "inl: port=0x%04x\n", addr);
+    return 0;
+}
+
+int cpu_get_pic_interrupt(CPUState *env)
+{
+    return -1;
+}
+#ifdef TARGET_PPC
+
+static inline uint64_t cpu_ppc_get_tb (CPUState *env)
+{
+    /* TO FIX */
+    return 0;
+}
+
+uint32_t cpu_ppc_load_tbl (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUState *env)
+{
+    return cpu_ppc_get_tb(env) >> 32;
+}
+
+static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+}
+
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+    cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+}
+
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+    /* TO FIX */
+    return -1;
+}
+
+void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+{
+    /* TO FIX */
+}
+
+void cpu_loop(CPUPPCState *env)
+{
+    int trapnr;
+    uint32_t ret;
+    target_siginfo_t info;
+
+    for(;;) {
+        trapnr = cpu_ppc_exec(env);
+        if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
+            trapnr != EXCP_TRACE) {
+            if (loglevel > 0) {
+                cpu_dump_state(env, logfile, fprintf, 0);
+            }
+        }
+        switch(trapnr) {
+        case EXCP_NONE:
+            break;
+        case EXCP_SYSCALL_USER:
+            /* 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_RESET:
+            /* Should not happen ! */
+            fprintf(stderr, "RESET asked... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                abort();
+        case EXCP_MACHINE_CHECK:
+            fprintf(stderr, "Machine check exeption...  Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "RESET asked... Stop emulation\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_OBJERR;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+        case EXCP_DSI:
+#ifndef DAR
+/* To deal with multiple qemu header version as host for the darwin-user code */
+# define DAR SPR_DAR
+#endif
+            fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
+            if (loglevel) {
+                fprintf(logfile, "Invalid data memory access: 0x%08x\n",
+                        env->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 EXCP_ISI:
+            fprintf(stderr, "Invalid instruction fetch\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid instruction fetch\n");
+            /* Handle this via the gdb */
+            gdb_handlesig (env, SIGSEGV);
+
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_EXTERNAL:
+            /* Should not happen ! */
+            fprintf(stderr, "External interruption... Stop emulation\n");
+            if (loglevel)
+                fprintf(logfile, "External interruption... Stop emulation\n");
+                abort();
+        case EXCP_ALIGN:
+            fprintf(stderr, "Invalid unaligned memory access\n");
+            if (loglevel)
+                fprintf(logfile, "Invalid unaligned memory access\n");
+                info.si_signo = SIGBUS;
+            info.si_errno = 0;
+            info.si_code = BUS_ADRALN;
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_PROGRAM:
+            switch (env->error_code & ~0xF) {
+                case EXCP_FP:
+                    fprintf(stderr, "Program exception\n");
+                    if (loglevel)
+                        fprintf(logfile, "Program exception\n");
+                        /* Set FX */
+                        env->fpscr[7] |= 0x8;
+                    /* Finally, update FEX */
+                    if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
+                        ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
+                        env->fpscr[7] |= 0x4;
+                        info.si_signo = SIGFPE;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_FP_OX:
+                            info.si_code = FPE_FLTOVF;
+                            break;
+                        case EXCP_FP_UX:
+                            info.si_code = FPE_FLTUND;
+                            break;
+                        case EXCP_FP_ZX:
+                        case EXCP_FP_VXZDZ:
+                            info.si_code = FPE_FLTDIV;
+                            break;
+                        case EXCP_FP_XX:
+                            info.si_code = FPE_FLTRES;
+                            break;
+                        case EXCP_FP_VXSOFT:
+                            info.si_code = FPE_FLTINV;
+                            break;
+                        case EXCP_FP_VXNAN:
+                        case EXCP_FP_VXISI:
+                        case EXCP_FP_VXIDI:
+                        case EXCP_FP_VXIMZ:
+                        case EXCP_FP_VXVC:
+                        case EXCP_FP_VXSQRT:
+                        case EXCP_FP_VXCVI:
+                            info.si_code = FPE_FLTSUB;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown floating point exception "
+                                    "(%02x)\n", env->error_code);
+                            if (loglevel) {
+                                fprintf(logfile, "Unknown floating point exception "
+                                        "(%02x)\n", env->error_code & 0xF);
+                            }
+                    }
+                        break;
+                case EXCP_INVAL:
+                    fprintf(stderr, "Invalid instruction\n");
+                    if (loglevel)
+                        fprintf(logfile, "Invalid instruction\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_INVAL_INVAL:
+                            info.si_code = ILL_ILLOPC;
+                            break;
+                        case EXCP_INVAL_LSWX:
+                            info.si_code = ILL_ILLOPN;
+                            break;
+                        case EXCP_INVAL_SPR:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        case EXCP_INVAL_FP:
+                            info.si_code = ILL_COPROC;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown invalid operation (%02x)\n",
+                                    env->error_code & 0xF);
+                            if (loglevel) {
+                                fprintf(logfile, "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 EXCP_PRIV:
+                    fprintf(stderr, "Privilege violation\n");
+                    if (loglevel)
+                        fprintf(logfile, "Privilege violation\n");
+                        info.si_signo = SIGILL;
+                    info.si_errno = 0;
+                    switch (env->error_code & 0xF) {
+                        case EXCP_PRIV_OPC:
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                        case EXCP_PRIV_REG:
+                            info.si_code = ILL_PRVREG;
+                            break;
+                        default:
+                            fprintf(stderr, "Unknown privilege violation (%02x)\n",
+                                    env->error_code & 0xF);
+                            info.si_code = ILL_PRVOPC;
+                            break;
+                    }
+                        break;
+                case EXCP_TRAP:
+                    fprintf(stderr, "Tried to call a TRAP\n");
+                    if (loglevel)
+                        fprintf(logfile, "Tried to call a TRAP\n");
+                        abort();
+                default:
+                    /* Should not happen ! */
+                    fprintf(stderr, "Unknown program exception (%02x)\n",
+                            env->error_code);
+                    if (loglevel) {
+                        fprintf(logfile, "Unknwon program exception (%02x)\n",
+                                env->error_code);
+                    }
+                        abort();
+            }
+            info.si_addr = (void*)(env->nip - 4);
+            queue_signal(info.si_signo, &info);
+            break;
+        case EXCP_NO_FP:
+            fprintf(stderr, "No floating point allowed\n");
+            if (loglevel)
+                fprintf(logfile, "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 EXCP_DECR:
+            /* Should not happen ! */
+            fprintf(stderr, "Decrementer exception\n");
+            if (loglevel)
+                fprintf(logfile, "Decrementer exception\n");
+            abort();
+        case EXCP_TRACE:
+            /* Pass to gdb: we use this to trace execution */
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        case EXCP_FP_ASSIST:
+            /* Should not happen ! */
+            fprintf(stderr, "Floating point assist exception\n");
+            if (loglevel)
+                fprintf(logfile, "Floating point assist exception\n");
+            abort();
+        case EXCP_MTMSR:
+            /* We reloaded the msr, just go on */
+            if (msr_pr == 0) {
+                fprintf(stderr, "Tried to go into supervisor mode !\n");
+                if (loglevel)
+                    fprintf(logfile, "Tried to go into supervisor mode !\n");
+                abort();
+            }
+            break;
+        case EXCP_BRANCH:
+            /* We stopped because of a jump... */
+            break;
+        case EXCP_INTERRUPT:
+            /* Don't know why this should ever happen... */
+            fprintf(stderr, "EXCP_INTERRUPT\n");
+            break;
+        case EXCP_DEBUG:
+            gdb_handlesig (env, SIGTRAP);
+            break;
+        default:
+            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
+                    trapnr);
+            if (loglevel) {
+                fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
+                        "0x%02x - aborting\n", trapnr, env->error_code);
+            }
+                abort();
+        }
+        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 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
+
+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 elf interpreter prefix (default=%s)\n"
+           "-s size      set the stack size in bytes (default=%ld)\n"
+           "\n"
+           "debug options:\n"
+#ifdef USE_CODE_COPY
+           "-no-code-copy   disable code copy acceleration\n"
+#endif
+           "-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",
+           TARGET_ARCH,
+           interp_prefix,
+           stack_size,
+           DEBUG_LOGFILE);
+    _exit(1);
+}
+
+/* XXX: currently only used for async signals (see signal.c) */
+CPUState *global_env;
+/* used only if single thread */
+CPUState *cpu_single_env = NULL;
+
+/* used to free thread contexts */
+TaskState *first_task_state;
+
+int main(int argc, char **argv)
+{
+    const char *filename;
+    struct target_pt_regs regs1, *regs = &regs1;
+    TaskState ts1, *ts = &ts1;
+    CPUState *env;
+    int optind;
+    short use_gdbstub = 0;
+    const char *r;
+
+    if (argc <= 1)
+        usage();
+
+    /* init debug */
+    cpu_set_log_filename(DEBUG_LOGFILE);
+
+    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")) {
+            int mask;
+            CPULogItem *item;
+
+        if (optind >= argc)
+        break;
+
+        r = argv[optind++];
+            mask = cpu_str_to_log_mask(r);
+            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);
+        } 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
+#ifdef USE_CODE_COPY
+        if (!strcmp(r, "no-code-copy")) {
+            code_copy_enabled = 0;
+        } else
+#endif
+        {
+            usage();
+        }
+    }
+    if (optind >= argc)
+        usage();
+    filename = argv[optind];
+
+    /* Zero out regs */
+    memset(regs, 0, sizeof(struct target_pt_regs));
+
+#if 0
+    /* Scan interp_prefix dir for replacement files. */
+    init_paths(interp_prefix);
+#endif
+
+    /* NOTE: we need to init the CPU at this stage to get
+       qemu_host_page_size */
+    env = cpu_init();
+
+    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;
+    env->user_mode_only = 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); /* Unix Syscall 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;
+        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
new file mode 100644 (file)
index 0000000..ada613d
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#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 -EINVAL;
+
+        /* 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 kenel 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
new file mode 100644 (file)
index 0000000..4d7713b
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef GEMU_H
+#define GEMU_H
+
+#include "thunk.h"
+
+#include <signal.h>
+#include <string.h>
+
+#include "cpu.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, ...) __attribute__((format(printf,1,2)));
+void qerror(const char *fmt, ...);
+
+void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
+
+extern CPUState *global_env;
+void cpu_loop(CPUState *env);
+void init_paths(const char *prefix);
+const char *path(const char *pathname);
+
+extern int loglevel;
+extern FILE *logfile;
+
+/* commpage.c */
+void commpage_init();
+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(CPUState *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
new file mode 100644 (file)
index 0000000..a0b9f89
--- /dev/null
@@ -0,0 +1,463 @@
+/*
+ *  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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+
+#ifdef __ia64__
+#undef uc_mcontext
+#undef uc_sigmask
+#undef uc_stack
+#undef uc_link
+#endif
+
+#include <signal.h>
+
+#include "qemu.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 */
+};
+
+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 __attribute((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 defined(TARGET_I386) && defined(USE_CODE_COPY)
+        || host_signum == SIGFPE
+#endif
+        ) {
+        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_interrupt(global_env, CPU_INTERRUPT_EXIT);
+    }
+}
+
+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",
+            act->sa_handler, act->sa_flags, act->sa_mask);
+#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, CPUState *env)
+{
+       void *frame;
+       int i, err = 0;
+
+    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(CPUState *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, CPUState *env)
+{
+    fprintf(stderr, "setup_frame: not implemented\n");
+}
+
+long do_sigreturn(CPUState *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
new file mode 100644 (file)
index 0000000..50725e6
--- /dev/null
@@ -0,0 +1,1315 @@
+/*
+ *  Darwin syscalls
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *  Copyright (c) 2006 Pierre d'Herbemont
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <mach/message.h>
+#include <mach/mach.h>
+#include <mach/mach_time.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 "qemu.h"
+
+//#define DEBUG_SYSCALL
+
+#ifdef DEBUG_SYSCALL
+# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
+# define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
+# define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
+
+# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
+# define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
+    DEBUG_ENABLE_ALL();
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
+                           if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
+                         } while(0)
+#else
+# define DEBUG_FORCE_ENABLE_LOCAL()
+# define DEBUG_BEGIN_ENABLE
+# define DEBUG_END_ENABLE
+
+# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
+#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 < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+        if(msg_name[i].number == hdr->msgh_id)
+        {
+            name = msg_name[i].name;
+            break;
+        }
+    }
+    if(!name)
+        DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
+    else
+        DPRINTF("%s\n", name);
+#if 0
+    DPRINTF("Bits: %8x\n", hdr->msgh_bits);
+    DPRINTF("Size: %8x\n", hdr->msgh_size);
+    DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
+    DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
+    DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
+
+    DPRINTF("Id  : %8x\n", hdr->msgh_id);
+
+    NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
+    DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
+    DPRINTF("%d %d %d %d %d %d %d %d\n",
+           ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
+           ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
+#endif
+}
+
+static inline void print_mach_msg_return(mach_msg_return_t ret)
+{
+    int i, found = 0;
+#define MACH_MSG_RET(msg) { msg, #msg }
+    struct { int code; char *name; } msg_name[] =
+    {
+        /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
+        /* send message */
+        MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
+        MACH_MSG_RET(MACH_SEND_NO_BUFFER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DATA),
+        MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
+        MACH_MSG_RET(MACH_SEND_INVALID_DEST),
+        MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
+        MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
+        MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
+        MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
+        MACH_MSG_RET(MACH_SEND_INTERRUPTED),
+        MACH_MSG_RET(MACH_SEND_TIMED_OUT),
+
+        MACH_MSG_RET(MACH_RCV_BODY_ERROR),
+        MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
+
+        MACH_MSG_RET(MACH_RCV_IN_SET),
+        MACH_MSG_RET(MACH_RCV_INTERRUPTED),
+
+        MACH_MSG_RET(MACH_RCV_INVALID_DATA),
+        MACH_MSG_RET(MACH_RCV_INVALID_NAME),
+        MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
+        MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
+        MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
+
+        MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
+        MACH_MSG_RET(MACH_RCV_PORT_DIED),
+
+        MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
+        MACH_MSG_RET(MACH_RCV_TIMED_OUT),
+        MACH_MSG_RET(MACH_RCV_TOO_LARGE)
+    };
+#undef MACH_MSG_RET
+
+    if( ret == MACH_MSG_SUCCESS)
+        DPRINTF("MACH_MSG_SUCCESS\n");
+    else
+    {
+        for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
+            if(msg_name[0].code & ret) {
+                DPRINTF("%s ", msg_name[0].name);
+                found = 1;
+            }
+        }
+        if(!found)
+            qerror("unknow mach message ret code %d\n", ret);
+        else
+            DPRINTF("\n");
+    }
+}
+
+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;
+    void *additional_data;
+
+    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);
+    additional_data = descr;
+    return additional_data;
+}
+
+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 *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+    mach_msg_audit_trailer_t *trailer;
+    mach_msg_id_t msg_id;
+    uint32_t ret = 0;
+    char *additional_data;
+    int i;
+
+    swap_mach_msg_header(hdr);
+
+    print_description_msg_header(hdr);
+
+    msg_id = hdr->msgh_id;
+
+    if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        additional_data = swap_mach_msg_body((struct complex_msg *)hdr, bswap_in);
+    else
+        additional_data = (void*)(hdr+1);
+
+    ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
+
+    print_mach_msg_return(ret);
+
+    if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
+        additional_data = swap_mach_msg_body((struct complex_msg *)hdr, bswap_out);
+    else
+        additional_data = (void*)(hdr+1);
+
+    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 maxcpu;
+                uint32_t numcpu;
+                uint32_t memsize;
+                uint32_t cpu_type;
+                uint32_t cpu_subtype;
+            } *data = (void *)(err+1);
+
+            DPRINTF("maxcpu = 0x%x\n",   data->maxcpu);
+            DPRINTF("numcpu = 0x%x\n",   data->maxcpu);
+            DPRINTF("memsize = 0x%x\n",  data->memsize);
+
+#if defined(TARGET_I386)
+            data->cpu_type = CPU_TYPE_I386;
+            DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
+#elif defined(TARGET_PPC)
+            data->cpu_type = CPU_TYPE_POWERPC;
+            DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
+#else
+# error target not supported
+#endif
+
+#if defined(TARGET_I386)
+            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_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_header(hdr);
+
+    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();
+
+    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;
+    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;
+    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;
+    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();
+    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, list...) STRUCT_ ## name,
+#define STRUCT_SPECIAL(name) STRUCT_ ## name,
+enum {
+#include "ioctls_types.h"
+};
+#undef STRUCT
+#undef STRUCT_SPECIAL
+
+#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, 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
+
+IOCTLEntry ioctl_entries[] = {
+#define IOCTL(cmd, access, types...) \
+    { cmd, cmd, #cmd, access, { types } },
+#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.lenght %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();
+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(void * arg1, uint32_t arg2, void * arg3, void * arg4, void * arg5, size_t arg6);
+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 no_syscall(void *cpu_env, int num);
+
+long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
+{
+    //DPRINTF("0x%x, 0x%x, 0x%x, 0x%llx\n", arg1, arg2, arg3, arg4);
+    long ret = (pread(arg1, arg2, arg3, arg4));
+    DPRINTF("0x%x\n", *(int*)arg2);
+    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, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
+#define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
+#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
+#define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, 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, args...) 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 accross 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()
+{
+    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);
+}
+
+long do___sysctl(void * arg1, uint32_t arg2, void * arg3, void * arg4, void * arg5, size_t arg6)
+{
+    long ret = 0;
+    int i;
+    DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
+            arg1, arg2, arg3, arg4, arg5, arg6);
+    if(arg1) {
+        i = 0;
+        do { *((int *) arg1 + i) = tswap32(*((int *) arg1 + i)); } while (++i < arg2);
+    }
+
+    if(arg4)
+        *(int *) arg4 = tswap32(*(int *) arg4);
+    if(arg1)
+    ret = get_errno(sysctl((void *)arg1, arg2, (void *)arg3, (void *)arg4, (void *)arg5, arg6));
+
+    if ((ret == 0) && (arg2 == 2) && (*((int *) arg1) == 0) && (*((int *) arg1 + 1) == 3)) {
+        /* The output here is the new id - we need to swap it so it can be passed
+        back in (and then unswapped) */
+        int count = (*(int *) arg4) / sizeof(int);
+        i = 0;
+        do {
+            *((int *) arg3 + i) = tswap32(*((int *) arg3 + i));
+        } while (++i < count);
+    }
+    *(int *) arg4 = tswap32(*(int *) arg4);
+
+    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__)
+    qerror("SYS_getdirentriesattr unimplemented\n");
+#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));
+}
+
+
+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
new file mode 100644 (file)
index 0000000..d04295b
--- /dev/null
@@ -0,0 +1,384 @@
+/* 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,                           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,                           unimpl_unix_syscall,               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,                          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,                      no_syscall,                        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  */
index a5e68ae03f11970447401346717ab8a95b819abf..9015d625ced6606d5b49b9cb1cc377219be48126 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -810,7 +810,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
             goto breakpoint_error;
         }
         break;
-#ifdef CONFIG_USER_ONLY
+#ifdef CONFIG_LINUX_USER
     case 'q':
         if (strncmp(p, "Offsets", 7) == 0) {
             TaskState *ts = env->opaque;