Commit 831b78254cfa752d5e6542542a663468e650bcb3

Authored by ths
1 parent 54421cb1

Darwin userspace emulation, by Pierre d'Herbemont.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2332 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 11 of 13 files are displayed.

Makefile.target
... ... @@ -13,7 +13,11 @@ endif
13 13 TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
14 14 VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
15 15 CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
16   -ifdef CONFIG_USER_ONLY
  16 +ifdef CONFIG_DARWIN_USER
  17 +VPATH+=:$(SRC_PATH)/darwin-user
  18 +CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
  19 +endif
  20 +ifdef CONFIG_LINUX_USER
17 21 VPATH+=:$(SRC_PATH)/linux-user
18 22 CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
19 23 endif
... ... @@ -85,12 +89,14 @@ endif
85 89 ifdef USE_I386_LD
86 90 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
87 91 else
  92 +ifdef CONFIG_LINUX_USER
88 93 # WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
89 94 # that the kernel ELF loader considers as an executable. I think this
90 95 # is the simplest way to make it self virtualizable!
91 96 BASE_LDFLAGS+=-Wl,-shared
92 97 endif
93 98 endif
  99 +endif
94 100  
95 101 ifeq ($(ARCH),x86_64)
96 102 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
... ... @@ -98,8 +104,10 @@ endif
98 104  
99 105 ifeq ($(ARCH),ppc)
100 106 CPPFLAGS+= -D__powerpc__
  107 +ifdef CONFIG_LINUX_USER
101 108 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
102 109 endif
  110 +endif
103 111  
104 112 ifeq ($(ARCH),s390)
105 113 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
... ... @@ -186,6 +194,7 @@ BASE_LDFLAGS+=-p
186 194 main.o: BASE_CFLAGS+=-p
187 195 endif
188 196  
  197 +ifdef CONFIG_LINUX_USER
189 198 OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
190 199 elfload.o linuxload.o
191 200 ifdef TARGET_HAS_BFLT
... ... @@ -203,6 +212,12 @@ endif
203 212 ifeq ($(TARGET_ARCH), m68k)
204 213 OBJS+= m68k-sim.o m68k-semi.o
205 214 endif
  215 +endif #CONFIG_LINUX_USER
  216 +
  217 +ifdef CONFIG_DARWIN_USER
  218 +OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
  219 +endif
  220 +
206 221 SRCS:= $(OBJS:.o=.c)
207 222 OBJS+= libqemu.a
208 223  
... ...
configure
... ... @@ -94,7 +94,8 @@ cocoa="no"
94 94 check_gfx="yes"
95 95 check_gcc="yes"
96 96 softmmu="yes"
97   -user="no"
  97 +linux_user="no"
  98 +darwin_user="no"
98 99 build_docs="no"
99 100 uname_release=""
100 101  
... ... @@ -126,6 +127,7 @@ oss="yes"
126 127 Darwin)
127 128 bsd="yes"
128 129 darwin="yes"
  130 +darwin_user="yes"
129 131 OS_CFLAGS="-mdynamic-no-pic"
130 132 ;;
131 133 SunOS)
... ... @@ -134,7 +136,7 @@ solaris="yes"
134 136 *)
135 137 oss="yes"
136 138 linux="yes"
137   -user="yes"
  139 +linux_user="yes"
138 140 if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
139 141 kqemu="yes"
140 142 fi
... ... @@ -240,9 +242,13 @@ for opt do
240 242 ;;
241 243 --enable-system) softmmu="yes"
242 244 ;;
243   - --disable-user) user="no"
  245 + --disable-linux-user) linux_user="no"
244 246 ;;
245   - --enable-user) user="yes"
  247 + --enable-linux-user) linux_user="yes"
  248 + ;;
  249 + --disable-darwin-user) darwin_user="no"
  250 + ;;
  251 + --enable-darwin-user) darwin_user="yes"
246 252 ;;
247 253 --enable-uname-release=*) uname_release="$optarg"
248 254 ;;
... ... @@ -287,8 +293,10 @@ echo " --enable-fmod enable FMOD audio driver"
287 293 echo " --enabled-dsound enable DirectSound audio driver"
288 294 echo " --enable-system enable all system emulation targets"
289 295 echo " --disable-system disable all system emulation targets"
290   -echo " --enable-user enable all linux usermode emulation targets"
291   -echo " --disable-user disable all linux usermode emulation targets"
  296 +echo " --enable-linux-user enable all linux usermode emulation targets"
  297 +echo " --disable-linux-user disable all linux usermode emulation targets"
  298 +echo " --enable-darwin-user enable all darwin usermode emulation targets"
  299 +echo " --disable-darwin-user disable all darwin usermode emulation targets"
292 300 echo " --fmod-lib path to FMOD library"
293 301 echo " --fmod-inc path to FMOD includes"
294 302 echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
... ... @@ -408,8 +416,12 @@ if test -z "$target_list" ; then
408 416 target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
409 417 fi
410 418 # the following are Linux specific
411   - if [ "$user" = "yes" ] ; then
412   - target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user m68k-user $target_list"
  419 + if [ "$linux_user" = "yes" ] ; then
  420 + 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"
  421 + fi
  422 +# the following are Darwin specific
  423 + if [ "$darwin_user" = "yes" ] ; then
  424 + target_list="i386-darwin-user ppc-darwin-user $target_list"
413 425 fi
414 426 else
415 427 target_list=`echo "$target_list" | sed -e 's/,/ /g'`
... ... @@ -787,6 +799,16 @@ if expr $target : '.*-user' > /dev/null ; then
787 799 target_user_only="yes"
788 800 fi
789 801  
  802 +target_linux_user="no"
  803 +if expr $target : '.*-linux-user' > /dev/null ; then
  804 + target_linux_user="yes"
  805 +fi
  806 +
  807 +target_darwin_user="no"
  808 +if expr $target : '.*-darwin-user' > /dev/null ; then
  809 + target_darwin_user="yes"
  810 +fi
  811 +
790 812 if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
791 813 -a "$sdl" = "no" -a "$cocoa" = "no" ; then
792 814 echo "ERROR: QEMU requires SDL or Cocoa for graphical output"
... ... @@ -799,7 +821,7 @@ fi
799 821  
800 822 mkdir -p $target_dir
801 823 mkdir -p $target_dir/fpu
802   -if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
  824 +if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
803 825 mkdir -p $target_dir/nwfpe
804 826 fi
805 827 if test "$target_user_only" = "no" ; then
... ... @@ -894,6 +916,14 @@ if test "$target_user_only" = "yes" ; then
894 916 echo "CONFIG_USER_ONLY=yes" >> $config_mak
895 917 echo "#define CONFIG_USER_ONLY 1" >> $config_h
896 918 fi
  919 +if test "$target_linux_user" = "yes" ; then
  920 + echo "CONFIG_LINUX_USER=yes" >> $config_mak
  921 + echo "#define CONFIG_LINUX_USER 1" >> $config_h
  922 +fi
  923 +if test "$target_darwin_user" = "yes" ; then
  924 + echo "CONFIG_DARWIN_USER=yes" >> $config_mak
  925 + echo "#define CONFIG_DARWIN_USER 1" >> $config_h
  926 +fi
897 927  
898 928 if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
899 929 echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
... ...
darwin-user/commpage.c 0 โ†’ 100644
  1 + /*
  2 + * Commpage syscalls
  3 + *
  4 + * Copyright (c) 2006 Pierre d'Herbemont
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include <fcntl.h>
  21 +#include <stdio.h>
  22 +#include <stdlib.h>
  23 +#include <errno.h>
  24 +
  25 +#include <mach/message.h>
  26 +#include <mach/mach.h>
  27 +#include <mach/mach_time.h>
  28 +#include <sys/time.h>
  29 +#include <sys/mman.h>
  30 +#include <libkern/OSAtomic.h>
  31 +
  32 +#include "qemu.h"
  33 +
  34 +//#define DEBUG_COMMPAGE
  35 +
  36 +#ifdef DEBUG_COMMPAGE
  37 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
  38 +#else
  39 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
  40 +#endif
  41 +
  42 +/********************************************************************
  43 + * Commpage definitions
  44 + */
  45 +#ifdef TARGET_I386
  46 +/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
  47 +# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
  48 +# define COMMPAGE_SIZE (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
  49 +#elif defined(TARGET_PPC)
  50 +/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
  51 +# define COMMPAGE_START (-8*4096)
  52 +# define COMMPAGE_SIZE (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
  53 +#endif
  54 +
  55 +void do_compare_and_swap32(void *cpu_env, int num);
  56 +void do_compare_and_swap64(void *cpu_env, int num);
  57 +void do_add_atomic_word32(void *cpu_env, int num);
  58 +void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
  59 +void do_nanotime(void *cpu_env, int num);
  60 +
  61 +void unimpl_commpage(void *cpu_env, int num);
  62 +
  63 +typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
  64 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  65 + uint32_t arg8);
  66 +typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
  67 + uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
  68 + uint32_t arg6, uint32_t arg7, uint32_t arg8);
  69 +
  70 +#define HAS_PTR 0x10
  71 +#define NO_PTR 0x20
  72 +#define CALL_DIRECT 0x1
  73 +#define CALL_INDIRECT 0x2
  74 +
  75 +#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
  76 + { #name, offset, nargs, options, (commpage_8args_function_t)func }
  77 +
  78 +struct commpage_entry {
  79 + char * name;
  80 + int offset;
  81 + int nargs;
  82 + char options;
  83 + commpage_8args_function_t function;
  84 +};
  85 +
  86 +static inline int commpage_code_num(struct commpage_entry *entry)
  87 +{
  88 + if((entry->options & HAS_PTR))
  89 + return entry->offset + 4;
  90 + else
  91 + return entry->offset;
  92 +}
  93 +
  94 +static inline int commpage_is_indirect(struct commpage_entry *entry)
  95 +{
  96 + return !(entry->options & CALL_DIRECT);
  97 +}
  98 +
  99 +/********************************************************************
  100 + * Commpage entry
  101 + */
  102 +static struct commpage_entry commpage_entries[] =
  103 +{
  104 + COMMPAGE_ENTRY(compare_and_swap32, 0, 0x080, do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
  105 + COMMPAGE_ENTRY(compare_and_swap64, 0, 0x0c0, do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
  106 + COMMPAGE_ENTRY(enqueue, 0, 0x100, unimpl_commpage, CALL_INDIRECT),
  107 + COMMPAGE_ENTRY(dequeue, 0, 0x140, unimpl_commpage, CALL_INDIRECT),
  108 + COMMPAGE_ENTRY(memory_barrier, 0, 0x180, unimpl_commpage, CALL_INDIRECT),
  109 + COMMPAGE_ENTRY(add_atomic_word32, 0, 0x1a0, do_add_atomic_word32, CALL_INDIRECT | HAS_PTR),
  110 + COMMPAGE_ENTRY(add_atomic_word64, 0, 0x1c0, unimpl_commpage, CALL_INDIRECT | HAS_PTR),
  111 +
  112 + COMMPAGE_ENTRY(mach_absolute_time, 0, 0x200, unimpl_commpage, CALL_INDIRECT),
  113 + COMMPAGE_ENTRY(spinlock_try, 1, 0x220, unimpl_commpage, CALL_INDIRECT),
  114 + COMMPAGE_ENTRY(spinlock_lock, 1, 0x260, OSSpinLockLock, CALL_DIRECT),
  115 + COMMPAGE_ENTRY(spinlock_unlock, 1, 0x2a0, OSSpinLockUnlock, CALL_DIRECT),
  116 + COMMPAGE_ENTRY(pthread_getspecific, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
  117 + COMMPAGE_ENTRY(gettimeofday, 1, 0x2c0, do_cgettimeofday, CALL_INDIRECT),
  118 + COMMPAGE_ENTRY(sys_dcache_flush, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
  119 + COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
  120 + COMMPAGE_ENTRY(pthread_self, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
  121 +
  122 + COMMPAGE_ENTRY(relinquish, 0, 0x5c0, unimpl_commpage, CALL_INDIRECT),
  123 +
  124 +#ifdef TARGET_I386
  125 + COMMPAGE_ENTRY(bts, 0, 0x5e0, unimpl_commpage, CALL_INDIRECT),
  126 + COMMPAGE_ENTRY(btc, 0, 0x5f0, unimpl_commpage, CALL_INDIRECT),
  127 +#endif
  128 +
  129 + COMMPAGE_ENTRY(bzero, 2, 0x600, bzero, CALL_DIRECT),
  130 + COMMPAGE_ENTRY(bcopy, 3, 0x780, bcopy, CALL_DIRECT),
  131 + COMMPAGE_ENTRY(memcpy, 3, 0x7a0, memcpy, CALL_DIRECT),
  132 +
  133 +#ifdef TARGET_I386
  134 + COMMPAGE_ENTRY(old_nanotime, 0, 0xf80, do_nanotime, CALL_INDIRECT),
  135 + COMMPAGE_ENTRY(memset_pattern, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
  136 + COMMPAGE_ENTRY(long_copy, 0, 0x1200, unimpl_commpage, CALL_INDIRECT),
  137 +
  138 + COMMPAGE_ENTRY(sysintegrity, 0, 0x1600, unimpl_commpage, CALL_INDIRECT),
  139 +
  140 + COMMPAGE_ENTRY(nanotime, 0, 0x1700, do_nanotime, CALL_INDIRECT),
  141 +#elif TARGET_PPC
  142 + COMMPAGE_ENTRY(compare_and_swap32b, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
  143 + COMMPAGE_ENTRY(compare_and_swap64b, 0, 0xfc0, unimpl_commpage, CALL_INDIRECT),
  144 + COMMPAGE_ENTRY(memset_pattern, 0, 0x1000, unimpl_commpage, CALL_INDIRECT),
  145 + COMMPAGE_ENTRY(bigcopy, 0, 0x1140, unimpl_commpage, CALL_INDIRECT),
  146 +#endif
  147 +};
  148 +
  149 +
  150 +/********************************************************************
  151 + * Commpage backdoor
  152 + */
  153 +static inline void print_commpage_entry(struct commpage_entry entry)
  154 +{
  155 + printf("@0x%x %s\n", entry.offset, entry.name);
  156 +}
  157 +
  158 +static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
  159 +{
  160 +#ifdef TARGET_I386
  161 + char * commpage = (char*)(COMMPAGE_START+entry.offset);
  162 + int c = 0;
  163 + if(entry.options & HAS_PTR)
  164 + {
  165 + commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
  166 + commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
  167 + commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
  168 + commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
  169 + }
  170 + commpage[c++] = 0xcd;
  171 + commpage[c++] = 0x79; /* int 0x79 */
  172 + commpage[c++] = 0xc3; /* ret */
  173 +#else
  174 + qerror("can't install the commpage on this arch\n");
  175 +#endif
  176 +}
  177 +
  178 +/********************************************************************
  179 + * Commpage initialization
  180 + */
  181 +void commpage_init(void)
  182 +{
  183 +#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(__powerpc__) ^ defined(TARGET_PPC))
  184 + int i;
  185 + void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
  186 + PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  187 + if((int)commpage != COMMPAGE_START)
  188 + qerror("can't allocate the commpage\n");
  189 +
  190 + bzero(commpage, COMMPAGE_SIZE);
  191 +
  192 + /* XXX: commpage data not handled */
  193 +
  194 + for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++)
  195 + install_commpage_backdoor_for_entry(commpage_entries[i]);
  196 +#else
  197 + /* simply map our pages so they can be executed
  198 + XXX: we don't really want to do that since in the ppc on ppc situation we may
  199 + not able to run commpages host optimized instructions (like G5's on a G5),
  200 + hence this is sometimes a broken fix. */
  201 + page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
  202 +#endif
  203 +}
  204 +
  205 +/********************************************************************
  206 + * Commpage implementation
  207 + */
  208 +void do_compare_and_swap32(void *cpu_env, int num)
  209 +{
  210 +#ifdef TARGET_I386
  211 + uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
  212 + uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
  213 + DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
  214 +
  215 + if(value && old == tswap32(*value))
  216 + {
  217 + uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
  218 + *value = tswap32(new);
  219 + /* set zf flag */
  220 + ((CPUX86State*)cpu_env)->eflags |= 0x40;
  221 + }
  222 + else
  223 + {
  224 + ((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
  225 + /* unset zf flag */
  226 + ((CPUX86State*)cpu_env)->eflags &= ~0x40;
  227 + }
  228 +#else
  229 + qerror("do_compare_and_swap32 unimplemented");
  230 +#endif
  231 +}
  232 +
  233 +void do_compare_and_swap64(void *cpu_env, int num)
  234 +{
  235 +#ifdef TARGET_I386
  236 + /* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
  237 + uint64_t old, new, swapped_val;
  238 + uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
  239 + old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
  240 +
  241 + DPRINTF("commpage: compare_and_swap64(%llx,new,%p)\n", old, value);
  242 + swapped_val = tswap64(*value);
  243 +
  244 + if(old == swapped_val)
  245 + {
  246 + new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
  247 + *value = tswap64(new);
  248 + /* set zf flag */
  249 + ((CPUX86State*)cpu_env)->eflags |= 0x40;
  250 + }
  251 + else
  252 + {
  253 + ((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
  254 + ((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
  255 + /* unset zf flag */
  256 + ((CPUX86State*)cpu_env)->eflags &= ~0x40;
  257 + }
  258 +#else
  259 + qerror("do_compare_and_swap64 unimplemented");
  260 +#endif
  261 +}
  262 +
  263 +void do_add_atomic_word32(void *cpu_env, int num)
  264 +{
  265 +#ifdef TARGET_I386
  266 + uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
  267 + uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
  268 + uint32_t swapped_value = tswap32(*value);
  269 +
  270 + DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
  271 +
  272 + /* old value in EAX */
  273 + ((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
  274 + *value = tswap32(swapped_value + amt);
  275 +#else
  276 + qerror("do_add_atomic_word32 unimplemented");
  277 +#endif
  278 +}
  279 +
  280 +void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
  281 +{
  282 +#ifdef TARGET_I386
  283 + extern int __commpage_gettimeofday(struct timeval *);
  284 + DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
  285 + struct timeval *time = (struct timeval *)arg1;
  286 + int ret = __commpage_gettimeofday(time);
  287 + tswap32s((uint32_t*)&time->tv_sec);
  288 + tswap32s((uint32_t*)&time->tv_usec);
  289 + ((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
  290 +#else
  291 + qerror("do_gettimeofday unimplemented");
  292 +#endif
  293 +}
  294 +
  295 +void do_nanotime(void *cpu_env, int num)
  296 +{
  297 +#ifdef TARGET_I386
  298 + uint64_t t = mach_absolute_time();
  299 + ((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
  300 + ((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
  301 +#else
  302 + qerror("do_nanotime unimplemented");
  303 +#endif
  304 +}
  305 +
  306 +void unimpl_commpage(void *cpu_env, int num)
  307 +{
  308 + gemu_log("qemu: commpage function 0x%x not implemented\n", num);
  309 +}
  310 +
  311 +/********************************************************************
  312 + * do_commpage - called by the main cpu loop
  313 + */
  314 +void
  315 +do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  316 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  317 + uint32_t arg8)
  318 +{
  319 + int i, found = 0;
  320 +
  321 + arg1 = tswap32(arg1);
  322 + arg2 = tswap32(arg2);
  323 + arg3 = tswap32(arg3);
  324 + arg4 = tswap32(arg4);
  325 + arg5 = tswap32(arg5);
  326 + arg6 = tswap32(arg6);
  327 + arg7 = tswap32(arg7);
  328 + arg8 = tswap32(arg8);
  329 +
  330 + num = num-COMMPAGE_START-2;
  331 +
  332 + for(i = 0; i < sizeof(commpage_entries)/sizeof(commpage_entries[0]); i++) {
  333 + if( num == commpage_code_num(&commpage_entries[i]) )
  334 + {
  335 + DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
  336 + found = 1;
  337 + if(commpage_is_indirect(&commpage_entries[i]))
  338 + {
  339 + commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
  340 + function(cpu_env, num, arg1, arg2, arg3,
  341 + arg4, arg5, arg6, arg7, arg8);
  342 + }
  343 + else
  344 + {
  345 + commpage_entries[i].function(arg1, arg2, arg3,
  346 + arg4, arg5, arg6, arg7, arg8);
  347 + }
  348 + break;
  349 + }
  350 + }
  351 +
  352 + if(!found)
  353 + {
  354 + gemu_log("qemu: commpage function 0x%x not defined\n", num);
  355 + gdb_handlesig (cpu_env, SIGTRAP);
  356 + exit(-1);
  357 + }
  358 +}
... ...
darwin-user/ioctls.h 0 โ†’ 100644
  1 + /* emulated ioctl list */
  2 +
  3 + IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
  4 + IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
... ...
darwin-user/ioctls_types.h 0 โ†’ 100644
  1 +STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)
0 2 \ No newline at end of file
... ...
darwin-user/machload.c 0 โ†’ 100644
  1 +/*
  2 + * Mach-O object file loading
  3 + *
  4 + * Copyright (c) 2006 Pierre d'Herbemont
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include <stdio.h>
  21 +#include <sys/types.h>
  22 +#include <fcntl.h>
  23 +#include <sys/stat.h>
  24 +#include <errno.h>
  25 +#include <unistd.h>
  26 +#include <sys/mman.h>
  27 +#include <stdlib.h>
  28 +#include <string.h>
  29 +
  30 +#include "qemu.h"
  31 +#include "disas.h"
  32 +
  33 +#include <mach-o/loader.h>
  34 +#include <mach-o/fat.h>
  35 +#include <mach-o/nlist.h>
  36 +#include <mach-o/reloc.h>
  37 +#include <mach-o/ppc/reloc.h>
  38 +
  39 +//#define DEBUG_MACHLOAD
  40 +
  41 +#ifdef DEBUG_MACHLOAD
  42 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); printf(__VA_ARGS__); } while(0)
  43 +#else
  44 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
  45 +#endif
  46 +
  47 +# define check_mach_header(x) (x.magic == MH_CIGAM)
  48 +
  49 +extern const char *interp_prefix;
  50 +
  51 +/* we don't have a good implementation for this */
  52 +#define DONT_USE_DYLD_SHARED_MAP
  53 +
  54 +/* Pass extra arg to DYLD for debug */
  55 +//#define ACTIVATE_DYLD_TRACE
  56 +
  57 +//#define OVERRIDE_DYLINKER
  58 +
  59 +#ifdef OVERRIDE_DYLINKER
  60 +# ifdef TARGET_I386
  61 +# define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
  62 +# else
  63 +# define DYLINKER_NAME "/usr/lib/dyld"
  64 +# endif
  65 +#endif
  66 +
  67 +/* XXX: in an include */
  68 +struct nlist_extended
  69 +{
  70 + union {
  71 + char *n_name;
  72 + long n_strx;
  73 + } n_un;
  74 + unsigned char n_type;
  75 + unsigned char n_sect;
  76 + short st_desc;
  77 + unsigned long st_value;
  78 + unsigned long st_size;
  79 +};
  80 +
  81 +/* Print symbols in gdb */
  82 +void *macho_text_sect = 0;
  83 +int macho_offset = 0;
  84 +
  85 +int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
  86 +void qerror(const char *format, ...);
  87 +#ifdef TARGET_I386
  88 +typedef struct mach_i386_thread_state {
  89 + unsigned int eax;
  90 + unsigned int ebx;
  91 + unsigned int ecx;
  92 + unsigned int edx;
  93 + unsigned int edi;
  94 + unsigned int esi;
  95 + unsigned int ebp;
  96 + unsigned int esp;
  97 + unsigned int ss;
  98 + unsigned int eflags;
  99 + unsigned int eip;
  100 + unsigned int cs;
  101 + unsigned int ds;
  102 + unsigned int es;
  103 + unsigned int fs;
  104 + unsigned int gs;
  105 +} mach_i386_thread_state_t;
  106 +
  107 +void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
  108 +{
  109 + bswap32s((uint32_t*)&ts->eax);
  110 + bswap32s((uint32_t*)&ts->ebx);
  111 + bswap32s((uint32_t*)&ts->ecx);
  112 + bswap32s((uint32_t*)&ts->edx);
  113 + bswap32s((uint32_t*)&ts->edi);
  114 + bswap32s((uint32_t*)&ts->esi);
  115 + bswap32s((uint32_t*)&ts->ebp);
  116 + bswap32s((uint32_t*)&ts->esp);
  117 + bswap32s((uint32_t*)&ts->ss);
  118 + bswap32s((uint32_t*)&ts->eflags);
  119 + bswap32s((uint32_t*)&ts->eip);
  120 + bswap32s((uint32_t*)&ts->cs);
  121 + bswap32s((uint32_t*)&ts->ds);
  122 + bswap32s((uint32_t*)&ts->es);
  123 + bswap32s((uint32_t*)&ts->fs);
  124 + bswap32s((uint32_t*)&ts->gs);
  125 +}
  126 +#define target_thread_state mach_i386_thread_state
  127 +#define TARGET_CPU_TYPE CPU_TYPE_I386
  128 +#define TARGET_CPU_NAME "i386"
  129 +#endif
  130 +
  131 +#ifdef TARGET_PPC
  132 +struct mach_ppc_thread_state {
  133 + unsigned int srr0; /* Instruction address register (PC) */
  134 + unsigned int srr1; /* Machine state register (supervisor) */
  135 + unsigned int r0;
  136 + unsigned int r1;
  137 + unsigned int r2;
  138 + unsigned int r3;
  139 + unsigned int r4;
  140 + unsigned int r5;
  141 + unsigned int r6;
  142 + unsigned int r7;
  143 + unsigned int r8;
  144 + unsigned int r9;
  145 + unsigned int r10;
  146 + unsigned int r11;
  147 + unsigned int r12;
  148 + unsigned int r13;
  149 + unsigned int r14;
  150 + unsigned int r15;
  151 + unsigned int r16;
  152 + unsigned int r17;
  153 + unsigned int r18;
  154 + unsigned int r19;
  155 + unsigned int r20;
  156 + unsigned int r21;
  157 + unsigned int r22;
  158 + unsigned int r23;
  159 + unsigned int r24;
  160 + unsigned int r25;
  161 + unsigned int r26;
  162 + unsigned int r27;
  163 + unsigned int r28;
  164 + unsigned int r29;
  165 + unsigned int r30;
  166 + unsigned int r31;
  167 +
  168 + unsigned int cr; /* Condition register */
  169 + unsigned int xer; /* User's integer exception register */
  170 + unsigned int lr; /* Link register */
  171 + unsigned int ctr; /* Count register */
  172 + unsigned int mq; /* MQ register (601 only) */
  173 +
  174 + unsigned int vrsave; /* Vector Save Register */
  175 +};
  176 +
  177 +void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
  178 +{
  179 + bswap32s((uint32_t*)&ts->srr0);
  180 + bswap32s((uint32_t*)&ts->srr1);
  181 + bswap32s((uint32_t*)&ts->r0);
  182 + bswap32s((uint32_t*)&ts->r1);
  183 + bswap32s((uint32_t*)&ts->r2);
  184 + bswap32s((uint32_t*)&ts->r3);
  185 + bswap32s((uint32_t*)&ts->r4);
  186 + bswap32s((uint32_t*)&ts->r5);
  187 + bswap32s((uint32_t*)&ts->r6);
  188 + bswap32s((uint32_t*)&ts->r7);
  189 + bswap32s((uint32_t*)&ts->r8);
  190 + bswap32s((uint32_t*)&ts->r9);
  191 + bswap32s((uint32_t*)&ts->r10);
  192 + bswap32s((uint32_t*)&ts->r11);
  193 + bswap32s((uint32_t*)&ts->r12);
  194 + bswap32s((uint32_t*)&ts->r13);
  195 + bswap32s((uint32_t*)&ts->r14);
  196 + bswap32s((uint32_t*)&ts->r15);
  197 + bswap32s((uint32_t*)&ts->r16);
  198 + bswap32s((uint32_t*)&ts->r17);
  199 + bswap32s((uint32_t*)&ts->r18);
  200 + bswap32s((uint32_t*)&ts->r19);
  201 + bswap32s((uint32_t*)&ts->r20);
  202 + bswap32s((uint32_t*)&ts->r21);
  203 + bswap32s((uint32_t*)&ts->r22);
  204 + bswap32s((uint32_t*)&ts->r23);
  205 + bswap32s((uint32_t*)&ts->r24);
  206 + bswap32s((uint32_t*)&ts->r25);
  207 + bswap32s((uint32_t*)&ts->r26);
  208 + bswap32s((uint32_t*)&ts->r27);
  209 + bswap32s((uint32_t*)&ts->r28);
  210 + bswap32s((uint32_t*)&ts->r29);
  211 + bswap32s((uint32_t*)&ts->r30);
  212 + bswap32s((uint32_t*)&ts->r31);
  213 +
  214 + bswap32s((uint32_t*)&ts->cr);
  215 + bswap32s((uint32_t*)&ts->xer);
  216 + bswap32s((uint32_t*)&ts->lr);
  217 + bswap32s((uint32_t*)&ts->ctr);
  218 + bswap32s((uint32_t*)&ts->mq);
  219 +
  220 + bswap32s((uint32_t*)&ts->vrsave);
  221 +}
  222 +
  223 +#define target_thread_state mach_ppc_thread_state
  224 +#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
  225 +#define TARGET_CPU_NAME "PowerPC"
  226 +#endif
  227 +
  228 +struct target_thread_command {
  229 + unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */
  230 + unsigned long cmdsize; /* total size of this command */
  231 + unsigned long flavor; /* flavor of thread state */
  232 + unsigned long count; /* count of longs in thread state */
  233 + struct target_thread_state state; /* thread state for this flavor */
  234 +};
  235 +
  236 +void bswap_tc(struct target_thread_command *tc)
  237 +{
  238 + bswap32s((uint32_t*)(&tc->flavor));
  239 + bswap32s((uint32_t*)&tc->count);
  240 +#if defined(TARGET_I386)
  241 + bswap_i386_thread_state(&tc->state);
  242 +#elif defined(TARGET_PPC)
  243 + bswap_ppc_thread_state(&tc->state);
  244 +#else
  245 +# error unknown TARGET_CPU_TYPE
  246 +#endif
  247 +}
  248 +
  249 +void bswap_mh(struct mach_header *mh)
  250 +{
  251 + bswap32s((uint32_t*)(&mh->magic));
  252 + bswap32s((uint32_t*)&mh->cputype);
  253 + bswap32s((uint32_t*)&mh->cpusubtype);
  254 + bswap32s((uint32_t*)&mh->filetype);
  255 + bswap32s((uint32_t*)&mh->ncmds);
  256 + bswap32s((uint32_t*)&mh->sizeofcmds);
  257 + bswap32s((uint32_t*)&mh->flags);
  258 +}
  259 +
  260 +void bswap_lc(struct load_command *lc)
  261 +{
  262 + bswap32s((uint32_t*)&lc->cmd);
  263 + bswap32s((uint32_t*)&lc->cmdsize);
  264 +}
  265 +
  266 +
  267 +void bswap_fh(struct fat_header *fh)
  268 +{
  269 + bswap32s((uint32_t*)&fh->magic);
  270 + bswap32s((uint32_t*)&fh->nfat_arch);
  271 +}
  272 +
  273 +void bswap_fa(struct fat_arch *fa)
  274 +{
  275 + bswap32s((uint32_t*)&fa->cputype);
  276 + bswap32s((uint32_t*)&fa->cpusubtype);
  277 + bswap32s((uint32_t*)&fa->offset);
  278 + bswap32s((uint32_t*)&fa->size);
  279 + bswap32s((uint32_t*)&fa->align);
  280 +}
  281 +
  282 +void bswap_segcmd(struct segment_command *sc)
  283 +{
  284 + bswap32s((uint32_t*)&sc->vmaddr);
  285 + bswap32s((uint32_t*)&sc->vmsize);
  286 + bswap32s((uint32_t*)&sc->fileoff);
  287 + bswap32s((uint32_t*)&sc->filesize);
  288 + bswap32s((uint32_t*)&sc->maxprot);
  289 + bswap32s((uint32_t*)&sc->initprot);
  290 + bswap32s((uint32_t*)&sc->nsects);
  291 + bswap32s((uint32_t*)&sc->flags);
  292 +}
  293 +
  294 +void bswap_symtabcmd(struct symtab_command *stc)
  295 +{
  296 + bswap32s((uint32_t*)&stc->cmd);
  297 + bswap32s((uint32_t*)&stc->cmdsize);
  298 + bswap32s((uint32_t*)&stc->symoff);
  299 + bswap32s((uint32_t*)&stc->nsyms);
  300 + bswap32s((uint32_t*)&stc->stroff);
  301 + bswap32s((uint32_t*)&stc->strsize);
  302 +}
  303 +
  304 +void bswap_sym(struct nlist *n)
  305 +{
  306 + bswap32s((uint32_t*)&n->n_un.n_strx);
  307 + bswap16s((uint16_t*)&n->n_desc);
  308 + bswap32s((uint32_t*)&n->n_value);
  309 +}
  310 +
  311 +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)
  312 +{
  313 + int entry;
  314 + if(need_bswap)
  315 + bswap_tc(tc);
  316 +#if defined(TARGET_I386)
  317 + entry = tc->state.eip;
  318 + 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",
  319 + tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
  320 + tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
  321 + tc->state.fs, tc->state.gs );
  322 +#define reg_copy(reg) regs->reg = tc->state.reg
  323 + if(regs)
  324 + {
  325 + reg_copy(eax);
  326 + reg_copy(ebx);
  327 + reg_copy(ecx);
  328 + reg_copy(edx);
  329 +
  330 + reg_copy(edi);
  331 + reg_copy(esi);
  332 +
  333 + reg_copy(ebp);
  334 + reg_copy(esp);
  335 +
  336 + reg_copy(eflags);
  337 + reg_copy(eip);
  338 + /*
  339 + reg_copy(ss);
  340 + reg_copy(cs);
  341 + reg_copy(ds);
  342 + reg_copy(es);
  343 + reg_copy(fs);
  344 + reg_copy(gs);*/
  345 + }
  346 +#undef reg_copy
  347 +#elif defined(TARGET_PPC)
  348 + entry = tc->state.srr0;
  349 +#endif
  350 + DPRINTF("load_thread: entry 0x%x\n", entry);
  351 + return entry;
  352 +}
  353 +
  354 +int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
  355 +{
  356 + int size;
  357 + char * dylinker_name;
  358 + size = dc->cmdsize - sizeof(struct dylinker_command);
  359 +
  360 + if(need_bswap)
  361 + dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
  362 + else
  363 + dylinker_name = (char*)((dc->name.offset)+(int)dc);
  364 +
  365 +#ifdef OVERRIDE_DYLINKER
  366 + dylinker_name = DYLINKER_NAME;
  367 +#else
  368 + if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
  369 + qerror("can't allocate the new dylinker name\n");
  370 +#endif
  371 +
  372 + DPRINTF("dylinker_name %s\n", dylinker_name);
  373 + return load_object(dylinker_name, NULL, NULL);
  374 +}
  375 +
  376 +int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
  377 +{
  378 + unsigned long addr = sc->vmaddr;
  379 + unsigned long size = sc->filesize;
  380 + unsigned long error = 0;
  381 +
  382 + if(need_bswap)
  383 + bswap_segcmd(sc);
  384 +
  385 + if(sc->vmaddr == 0)
  386 + {
  387 + DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
  388 + return -1;
  389 + }
  390 +
  391 + if (strcmp(sc->segname, "__PAGEZERO") == 0)
  392 + {
  393 + DPRINTF("load_segment: __PAGEZERO returning\n");
  394 + return -1;
  395 + }
  396 +
  397 + /* Right now mmap memory */
  398 + /* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
  399 + DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
  400 +
  401 + if(sc->filesize > 0)
  402 + {
  403 + int opt = 0;
  404 +
  405 + if(fixed)
  406 + opt |= MAP_FIXED;
  407 +
  408 + DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
  409 +
  410 + addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff);
  411 +
  412 + if(addr==-1)
  413 + qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
  414 +
  415 + error = addr-sc->vmaddr;
  416 + }
  417 + else
  418 + {
  419 + addr = sc->vmaddr+slide;
  420 + error = slide;
  421 + }
  422 +
  423 + if(sc->vmsize > sc->filesize)
  424 + {
  425 + addr += sc->filesize;
  426 + size = sc->vmsize-sc->filesize;
  427 + addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  428 + if(addr==-1)
  429 + qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
  430 + }
  431 +
  432 + return error;
  433 +}
  434 +
  435 +void *load_data(int fd, long offset, unsigned int size)
  436 +{
  437 + char *data;
  438 +
  439 + data = malloc(size);
  440 + if (!data)
  441 + return NULL;
  442 + lseek(fd, offset, SEEK_SET);
  443 + if (read(fd, data, size) != size) {
  444 + free(data);
  445 + return NULL;
  446 + }
  447 + return data;
  448 +}
  449 +
  450 +/* load a mach-o object file */
  451 +int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
  452 +{
  453 + int need_bswap = 0;
  454 + int entry_point = 0;
  455 + int dyld_entry_point = 0;
  456 + int slide, mmapfixed;
  457 + int fd;
  458 + struct load_command *lcmds, *lc;
  459 + int is_fat = 0;
  460 + unsigned int i, magic;
  461 + int mach_hdr_pos = 0;
  462 + struct mach_header mach_hdr;
  463 +
  464 + /* for symbol lookup whith -d flag. */
  465 + struct symtab_command * symtabcmd = 0;
  466 + struct nlist_extended *symtab, *sym;
  467 + struct nlist *symtab_std, *syment;
  468 + char *strtab;
  469 +
  470 + fd = open(filename, O_RDONLY);
  471 + if (fd < 0)
  472 + qerror("can't open file '%s'", filename);
  473 +
  474 + /* Read magic header. */
  475 + if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
  476 + qerror("unable to read Magic of '%s'", filename);
  477 +
  478 + /* Check Mach identification. */
  479 + if(magic == MH_MAGIC)
  480 + {
  481 + is_fat = 0;
  482 + need_bswap = 0;
  483 + } else if (magic == MH_CIGAM)
  484 + {
  485 + is_fat = 0;
  486 + need_bswap = 1;
  487 + } else if (magic == FAT_MAGIC)
  488 + {
  489 + is_fat = 1;
  490 + need_bswap = 0;
  491 + } else if (magic == FAT_CIGAM)
  492 + {
  493 + is_fat = 1;
  494 + need_bswap = 1;
  495 + }
  496 + else
  497 + qerror("Not a Mach-O file.", filename);
  498 +
  499 + DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
  500 + if(is_fat)
  501 + {
  502 + int found = 0;
  503 + struct fat_header fh;
  504 + struct fat_arch *fa;
  505 +
  506 + lseek(fd, 0, SEEK_SET);
  507 +
  508 + /* Read Fat header. */
  509 + if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
  510 + qerror("unable to read file header");
  511 +
  512 + if(need_bswap)
  513 + bswap_fh(&fh);
  514 +
  515 + /* Read Fat Arch. */
  516 + fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
  517 +
  518 + if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
  519 + qerror("unable to read file header");
  520 +
  521 + for( i = 0; i < fh.nfat_arch; i++, fa++)
  522 + {
  523 + if(need_bswap)
  524 + bswap_fa(fa);
  525 + if(fa->cputype == TARGET_CPU_TYPE)
  526 + {
  527 + mach_hdr_pos = fa->offset;
  528 + lseek(fd, mach_hdr_pos, SEEK_SET);
  529 +
  530 + /* Read Mach header. */
  531 +
  532 + if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
  533 + qerror("unable to read file header");
  534 +
  535 + if(mach_hdr.magic == MH_MAGIC)
  536 + need_bswap = 0;
  537 + else if (mach_hdr.magic == MH_CIGAM)
  538 + need_bswap = 1;
  539 + else
  540 + qerror("Invalid mach header in Fat Mach-O File");
  541 + found = 1;
  542 + break;
  543 + }
  544 + }
  545 + if(!found)
  546 + qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
  547 + }
  548 + else
  549 + {
  550 + lseek(fd, 0, SEEK_SET);
  551 + /* Read Mach header */
  552 + if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
  553 + qerror("%s: unable to read file header", filename);
  554 + }
  555 +
  556 + if(need_bswap)
  557 + bswap_mh(&mach_hdr);
  558 +
  559 + if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
  560 + qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
  561 +
  562 +
  563 + switch(mach_hdr.filetype)
  564 + {
  565 + case MH_EXECUTE: break;
  566 + case MH_FVMLIB:
  567 + case MH_DYLIB:
  568 + case MH_DYLINKER: break;
  569 + default:
  570 + qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
  571 + }
  572 +
  573 + /* read segment headers */
  574 + lcmds = malloc(mach_hdr.sizeofcmds);
  575 +
  576 + if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
  577 + qerror("%s: unable to read load_command", filename);
  578 + slide = 0;
  579 + mmapfixed = 0;
  580 + for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
  581 + {
  582 +
  583 + if(need_bswap)
  584 + bswap_lc(lc);
  585 + switch(lc->cmd)
  586 + {
  587 + case LC_SEGMENT:
  588 + /* The main_exe can't be relocated */
  589 + if(mach_hdr.filetype == MH_EXECUTE)
  590 + mmapfixed = 1;
  591 +
  592 + slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
  593 +
  594 + /* other segment must be mapped according to slide exactly, if load_segment did something */
  595 + if(slide != -1)
  596 + mmapfixed = 1;
  597 + else
  598 + slide = 0; /* load_segment didn't map the segment */
  599 +
  600 + if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
  601 + qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
  602 +
  603 + if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
  604 + {
  605 + /* Text section */
  606 + if(mach_hdr.filetype == MH_EXECUTE)
  607 + {
  608 + /* return the mach_header */
  609 + *mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
  610 + }
  611 + else
  612 + {
  613 + /* it is dyld save the section for gdb, we will be interested in dyld symbol
  614 + while debuging */
  615 + macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
  616 + macho_offset = slide;
  617 + }
  618 + }
  619 + break;
  620 + case LC_LOAD_DYLINKER:
  621 + dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
  622 + break;
  623 + case LC_LOAD_DYLIB:
  624 + /* dyld will do that for us */
  625 + break;
  626 + case LC_THREAD:
  627 + case LC_UNIXTHREAD:
  628 + {
  629 + struct target_pt_regs * _regs;
  630 + if(mach_hdr.filetype == MH_DYLINKER)
  631 + _regs = regs;
  632 + else
  633 + _regs = 0;
  634 + entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
  635 + }
  636 + break;
  637 + case LC_SYMTAB:
  638 + /* Save the symtab and strtab */
  639 + symtabcmd = (struct symtab_command *)lc;
  640 + break;
  641 + case LC_ID_DYLINKER:
  642 + case LC_ID_DYLIB:
  643 + case LC_UUID:
  644 + case LC_DYSYMTAB:
  645 + case LC_TWOLEVEL_HINTS:
  646 + case LC_PREBIND_CKSUM:
  647 + case LC_SUB_LIBRARY:
  648 + break;
  649 + default: fprintf(stderr, "warning: unkown command 0x%x in '%s'\n", lc->cmd, filename);
  650 + }
  651 + lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
  652 + }
  653 +
  654 + if(symtabcmd)
  655 + {
  656 + if(need_bswap)
  657 + bswap_symtabcmd(symtabcmd);
  658 +
  659 + symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
  660 + strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
  661 +
  662 + symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
  663 +
  664 + if(need_bswap)
  665 + {
  666 + for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
  667 + bswap_sym(syment);
  668 + }
  669 +
  670 + for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
  671 + {
  672 + struct nlist *sym_follow, *sym_next = 0;
  673 + unsigned int j;
  674 + memset(sym, 0, sizeof(*sym));
  675 +
  676 + sym->n_type = syment->n_type;
  677 + if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
  678 + continue;
  679 +
  680 + memcpy(sym, syment, sizeof(*syment));
  681 +
  682 + /* Find the following symbol in order to get the current symbol size */
  683 + for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
  684 + if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
  685 + continue;
  686 + if(!sym_next) {
  687 + sym_next = sym_follow;
  688 + continue;
  689 + }
  690 + if(!(sym_next->n_value > sym_follow->n_value))
  691 + continue;
  692 + sym_next = sym_follow;
  693 + }
  694 + if(sym_next)
  695 + sym->st_size = sym_next->n_value - sym->st_value;
  696 + else
  697 + sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
  698 +
  699 + sym->st_value += slide;
  700 + }
  701 +
  702 + free((void*)symtab_std);
  703 +
  704 + {
  705 + DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
  706 + struct syminfo *s;
  707 + s = malloc(sizeof(*s));
  708 + s->disas_symtab = symtab;
  709 + s->disas_strtab = strtab;
  710 + s->disas_num_syms = symtabcmd->nsyms;
  711 + s->next = syminfos;
  712 + syminfos = s;
  713 + }
  714 + }
  715 + close(fd);
  716 + if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
  717 + return dyld_entry_point;
  718 + else
  719 + return entry_point+slide;
  720 +}
  721 +
  722 +extern unsigned long stack_size;
  723 +
  724 +unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
  725 +{
  726 + unsigned long stack_base, error, size;
  727 + int i;
  728 + int * stack;
  729 + int argc, envc;
  730 +
  731 + /* Create enough stack to hold everything. If we don't use
  732 + * it for args, we'll use it for something else...
  733 + */
  734 + size = stack_size;
  735 +
  736 + error = target_mmap(0,
  737 + size + qemu_host_page_size,
  738 + PROT_READ | PROT_WRITE,
  739 + MAP_PRIVATE | MAP_ANONYMOUS,
  740 + -1, 0);
  741 + if (error == -1)
  742 + qerror("stk mmap");
  743 +
  744 + /* we reserve one extra page at the top of the stack as guard */
  745 + target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
  746 +
  747 + stack_base = error + size;
  748 + stack = (void*)stack_base;
  749 +/*
  750 + * | STRING AREA |
  751 + * +-------------+
  752 + * | 0 |
  753 +* +-------------+
  754 + * | apple[n] |
  755 + * +-------------+
  756 + * :
  757 + * +-------------+
  758 + * | apple[0] |
  759 + * +-------------+
  760 + * | 0 |
  761 + * +-------------+
  762 + * | env[n] |
  763 + * +-------------+
  764 + * :
  765 + * :
  766 + * +-------------+
  767 + * | env[0] |
  768 + * +-------------+
  769 + * | 0 |
  770 + * +-------------+
  771 + * | arg[argc-1] |
  772 + * +-------------+
  773 + * :
  774 + * :
  775 + * +-------------+
  776 + * | arg[0] |
  777 + * +-------------+
  778 + * | argc |
  779 + * +-------------+
  780 + * sp-> | mh | address of where the a.out's file offset 0 is in memory
  781 + * +-------------+
  782 +*/
  783 + /* Construct the stack Stack grows down */
  784 + stack--;
  785 +
  786 + /* XXX: string should go up there */
  787 +
  788 + *stack = 0;
  789 + stack--;
  790 +
  791 + /* Push the absolute path of our executable */
  792 + DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
  793 + stl(stack, (int) argv[0]);
  794 +
  795 + stack--;
  796 +
  797 + stl(stack, 0);
  798 + stack--;
  799 +
  800 + /* Get envc */
  801 + for(envc = 0; env[envc]; envc++);
  802 +
  803 + for(i = envc-1; i >= 0; i--)
  804 + {
  805 + DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
  806 + stl(stack, (int)env[i]);
  807 + stack--;
  808 +
  809 + /* XXX: remove that when string will be on top of the stack */
  810 + page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
  811 + }
  812 +
  813 + /* Add on the stack the interp_prefix choosen if so */
  814 + if(interp_prefix[0])
  815 + {
  816 + char *dyld_root;
  817 + asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
  818 + page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
  819 +
  820 + stl(stack, (int)dyld_root);
  821 + stack--;
  822 + }
  823 +
  824 +#ifdef DONT_USE_DYLD_SHARED_MAP
  825 + {
  826 + char *shared_map_mode;
  827 + asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
  828 + page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
  829 +
  830 + stl(stack, (int)shared_map_mode);
  831 + stack--;
  832 + }
  833 +#endif
  834 +
  835 +#ifdef ACTIVATE_DYLD_TRACE
  836 + char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
  837 + "DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
  838 + "DYLD_PRINT_INITIALIZERS=yes",
  839 + "DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
  840 +
  841 + char ** extra_env = malloc(sizeof(extra_env_static));
  842 + bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
  843 + page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
  844 +
  845 + for(i = 0; i<9; i++)
  846 + {
  847 + DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
  848 + stl(stack, (int) extra_env[i]);
  849 + stack--;
  850 + }
  851 +#endif
  852 +
  853 + stl(stack, 0);
  854 + stack--;
  855 +
  856 + /* Get argc */
  857 + for(argc = 0; argv[argc]; argc++);
  858 +
  859 + for(i = argc-1; i >= 0; i--)
  860 + {
  861 + DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
  862 + stl(stack, (int) argv[i]);
  863 + stack--;
  864 +
  865 + /* XXX: remove that when string will be on top of the stack */
  866 + page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
  867 + }
  868 +
  869 + DPRINTF("pushing argc %d \n", argc);
  870 + stl(stack, argc);
  871 + stack--;
  872 +
  873 + DPRINTF("pushing mh 0x%x \n", (int)mh);
  874 + stl(stack, (int) mh);
  875 +
  876 + /* Stack points on the mh */
  877 + return (unsigned long)stack;
  878 +}
  879 +
  880 +int mach_exec(const char * filename, char ** argv, char ** envp,
  881 + struct target_pt_regs * regs)
  882 +{
  883 + int entrypoint, stack;
  884 + void * mh; /* the Mach Header that will be used by dyld */
  885 +
  886 + DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
  887 +
  888 + entrypoint = load_object(filename, regs, &mh);
  889 + stack = setup_arg_pages(mh, argv, envp);
  890 +#if defined(TARGET_I386)
  891 + regs->eip = entrypoint;
  892 + regs->esp = stack;
  893 +#elif defined(TARGET_PPC)
  894 + regs->nip = entrypoint;
  895 + regs->gpr[1] = stack;
  896 +#endif
  897 + DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
  898 +
  899 + if(!entrypoint)
  900 + qerror("%s: no entry point!\n", filename);
  901 +
  902 + return 0;
  903 +}
... ...
darwin-user/main.c 0 โ†’ 100644
  1 +/*
  2 + * qemu user main
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + * Copyright (c) 2006 Pierre d'Herbemont
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 + */
  21 +#include <stdlib.h>
  22 +#include <stdio.h>
  23 +#include <stdarg.h>
  24 +#include <string.h>
  25 +#include <errno.h>
  26 +#include <unistd.h>
  27 +
  28 +#include <sys/syscall.h>
  29 +#include <sys/mman.h>
  30 +
  31 +#include "qemu.h"
  32 +
  33 +#define DEBUG_LOGFILE "/tmp/qemu.log"
  34 +
  35 +#ifdef __APPLE__
  36 +#include <crt_externs.h>
  37 +# define environ (*_NSGetEnviron())
  38 +#endif
  39 +
  40 +#include <mach/mach_init.h>
  41 +#include <mach/vm_map.h>
  42 +
  43 +const char *interp_prefix = "";
  44 +
  45 +asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
  46 +
  47 +/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
  48 + we allocate a bigger stack. Need a better solution, for example
  49 + by remapping the process stack directly at the right place */
  50 +unsigned long stack_size = 512 * 1024;
  51 +
  52 +void qerror(const char *fmt, ...)
  53 +{
  54 + va_list ap;
  55 +
  56 + va_start(ap, fmt);
  57 + vfprintf(stderr, fmt, ap);
  58 + va_end(ap);
  59 + fprintf(stderr, "\n");
  60 + exit(1);
  61 +}
  62 +
  63 +void gemu_log(const char *fmt, ...)
  64 +{
  65 + va_list ap;
  66 +
  67 + va_start(ap, fmt);
  68 + vfprintf(stderr, fmt, ap);
  69 + va_end(ap);
  70 +}
  71 +
  72 +void cpu_outb(CPUState *env, int addr, int val)
  73 +{
  74 + fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
  75 +}
  76 +
  77 +void cpu_outw(CPUState *env, int addr, int val)
  78 +{
  79 + fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
  80 +}
  81 +
  82 +void cpu_outl(CPUState *env, int addr, int val)
  83 +{
  84 + fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
  85 +}
  86 +
  87 +int cpu_inb(CPUState *env, int addr)
  88 +{
  89 + fprintf(stderr, "inb: port=0x%04x\n", addr);
  90 + return 0;
  91 +}
  92 +
  93 +int cpu_inw(CPUState *env, int addr)
  94 +{
  95 + fprintf(stderr, "inw: port=0x%04x\n", addr);
  96 + return 0;
  97 +}
  98 +
  99 +int cpu_inl(CPUState *env, int addr)
  100 +{
  101 + fprintf(stderr, "inl: port=0x%04x\n", addr);
  102 + return 0;
  103 +}
  104 +
  105 +int cpu_get_pic_interrupt(CPUState *env)
  106 +{
  107 + return -1;
  108 +}
  109 +#ifdef TARGET_PPC
  110 +
  111 +static inline uint64_t cpu_ppc_get_tb (CPUState *env)
  112 +{
  113 + /* TO FIX */
  114 + return 0;
  115 +}
  116 +
  117 +uint32_t cpu_ppc_load_tbl (CPUState *env)
  118 +{
  119 + return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
  120 +}
  121 +
  122 +uint32_t cpu_ppc_load_tbu (CPUState *env)
  123 +{
  124 + return cpu_ppc_get_tb(env) >> 32;
  125 +}
  126 +
  127 +static void cpu_ppc_store_tb (CPUState *env, uint64_t value)
  128 +{
  129 + /* TO FIX */
  130 +}
  131 +
  132 +void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
  133 +{
  134 + cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
  135 +}
  136 +
  137 +void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
  138 +{
  139 + cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
  140 +}
  141 +
  142 +uint32_t cpu_ppc_load_decr (CPUState *env)
  143 +{
  144 + /* TO FIX */
  145 + return -1;
  146 +}
  147 +
  148 +void cpu_ppc_store_decr (CPUState *env, uint32_t value)
  149 +{
  150 + /* TO FIX */
  151 +}
  152 +
  153 +void cpu_loop(CPUPPCState *env)
  154 +{
  155 + int trapnr;
  156 + uint32_t ret;
  157 + target_siginfo_t info;
  158 +
  159 + for(;;) {
  160 + trapnr = cpu_ppc_exec(env);
  161 + if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
  162 + trapnr != EXCP_TRACE) {
  163 + if (loglevel > 0) {
  164 + cpu_dump_state(env, logfile, fprintf, 0);
  165 + }
  166 + }
  167 + switch(trapnr) {
  168 + case EXCP_NONE:
  169 + break;
  170 + case EXCP_SYSCALL_USER:
  171 + /* system call */
  172 + if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
  173 + ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
  174 + env->gpr[5], env->gpr[6], env->gpr[7],
  175 + env->gpr[8], env->gpr[9], env->gpr[10]*/);
  176 + else if(((int)env->gpr[0])<0)
  177 + ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
  178 + env->gpr[5], env->gpr[6], env->gpr[7],
  179 + env->gpr[8], env->gpr[9], env->gpr[10]);
  180 + else
  181 + ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
  182 + env->gpr[5], env->gpr[6], env->gpr[7],
  183 + env->gpr[8], env->gpr[9], env->gpr[10]);
  184 +
  185 + /* Unix syscall error signaling */
  186 + if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
  187 + {
  188 + if( (int)ret < 0 )
  189 + env->nip += 0;
  190 + else
  191 + env->nip += 4;
  192 + }
  193 +
  194 + /* Return value */
  195 + env->gpr[3] = ret;
  196 + break;
  197 + case EXCP_RESET:
  198 + /* Should not happen ! */
  199 + fprintf(stderr, "RESET asked... Stop emulation\n");
  200 + if (loglevel)
  201 + fprintf(logfile, "RESET asked... Stop emulation\n");
  202 + abort();
  203 + case EXCP_MACHINE_CHECK:
  204 + fprintf(stderr, "Machine check exeption... Stop emulation\n");
  205 + if (loglevel)
  206 + fprintf(logfile, "RESET asked... Stop emulation\n");
  207 + info.si_signo = SIGBUS;
  208 + info.si_errno = 0;
  209 + info.si_code = BUS_OBJERR;
  210 + info.si_addr = (void*)(env->nip - 4);
  211 + queue_signal(info.si_signo, &info);
  212 + case EXCP_DSI:
  213 +#ifndef DAR
  214 +/* To deal with multiple qemu header version as host for the darwin-user code */
  215 +# define DAR SPR_DAR
  216 +#endif
  217 + fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
  218 + if (loglevel) {
  219 + fprintf(logfile, "Invalid data memory access: 0x%08x\n",
  220 + env->spr[DAR]);
  221 + }
  222 + /* Handle this via the gdb */
  223 + gdb_handlesig (env, SIGSEGV);
  224 +
  225 + info.si_addr = (void*)env->nip;
  226 + queue_signal(info.si_signo, &info);
  227 + break;
  228 + case EXCP_ISI:
  229 + fprintf(stderr, "Invalid instruction fetch\n");
  230 + if (loglevel)
  231 + fprintf(logfile, "Invalid instruction fetch\n");
  232 + /* Handle this via the gdb */
  233 + gdb_handlesig (env, SIGSEGV);
  234 +
  235 + info.si_addr = (void*)(env->nip - 4);
  236 + queue_signal(info.si_signo, &info);
  237 + break;
  238 + case EXCP_EXTERNAL:
  239 + /* Should not happen ! */
  240 + fprintf(stderr, "External interruption... Stop emulation\n");
  241 + if (loglevel)
  242 + fprintf(logfile, "External interruption... Stop emulation\n");
  243 + abort();
  244 + case EXCP_ALIGN:
  245 + fprintf(stderr, "Invalid unaligned memory access\n");
  246 + if (loglevel)
  247 + fprintf(logfile, "Invalid unaligned memory access\n");
  248 + info.si_signo = SIGBUS;
  249 + info.si_errno = 0;
  250 + info.si_code = BUS_ADRALN;
  251 + info.si_addr = (void*)(env->nip - 4);
  252 + queue_signal(info.si_signo, &info);
  253 + break;
  254 + case EXCP_PROGRAM:
  255 + switch (env->error_code & ~0xF) {
  256 + case EXCP_FP:
  257 + fprintf(stderr, "Program exception\n");
  258 + if (loglevel)
  259 + fprintf(logfile, "Program exception\n");
  260 + /* Set FX */
  261 + env->fpscr[7] |= 0x8;
  262 + /* Finally, update FEX */
  263 + if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
  264 + ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
  265 + env->fpscr[7] |= 0x4;
  266 + info.si_signo = SIGFPE;
  267 + info.si_errno = 0;
  268 + switch (env->error_code & 0xF) {
  269 + case EXCP_FP_OX:
  270 + info.si_code = FPE_FLTOVF;
  271 + break;
  272 + case EXCP_FP_UX:
  273 + info.si_code = FPE_FLTUND;
  274 + break;
  275 + case EXCP_FP_ZX:
  276 + case EXCP_FP_VXZDZ:
  277 + info.si_code = FPE_FLTDIV;
  278 + break;
  279 + case EXCP_FP_XX:
  280 + info.si_code = FPE_FLTRES;
  281 + break;
  282 + case EXCP_FP_VXSOFT:
  283 + info.si_code = FPE_FLTINV;
  284 + break;
  285 + case EXCP_FP_VXNAN:
  286 + case EXCP_FP_VXISI:
  287 + case EXCP_FP_VXIDI:
  288 + case EXCP_FP_VXIMZ:
  289 + case EXCP_FP_VXVC:
  290 + case EXCP_FP_VXSQRT:
  291 + case EXCP_FP_VXCVI:
  292 + info.si_code = FPE_FLTSUB;
  293 + break;
  294 + default:
  295 + fprintf(stderr, "Unknown floating point exception "
  296 + "(%02x)\n", env->error_code);
  297 + if (loglevel) {
  298 + fprintf(logfile, "Unknown floating point exception "
  299 + "(%02x)\n", env->error_code & 0xF);
  300 + }
  301 + }
  302 + break;
  303 + case EXCP_INVAL:
  304 + fprintf(stderr, "Invalid instruction\n");
  305 + if (loglevel)
  306 + fprintf(logfile, "Invalid instruction\n");
  307 + info.si_signo = SIGILL;
  308 + info.si_errno = 0;
  309 + switch (env->error_code & 0xF) {
  310 + case EXCP_INVAL_INVAL:
  311 + info.si_code = ILL_ILLOPC;
  312 + break;
  313 + case EXCP_INVAL_LSWX:
  314 + info.si_code = ILL_ILLOPN;
  315 + break;
  316 + case EXCP_INVAL_SPR:
  317 + info.si_code = ILL_PRVREG;
  318 + break;
  319 + case EXCP_INVAL_FP:
  320 + info.si_code = ILL_COPROC;
  321 + break;
  322 + default:
  323 + fprintf(stderr, "Unknown invalid operation (%02x)\n",
  324 + env->error_code & 0xF);
  325 + if (loglevel) {
  326 + fprintf(logfile, "Unknown invalid operation (%02x)\n",
  327 + env->error_code & 0xF);
  328 + }
  329 + info.si_code = ILL_ILLADR;
  330 + break;
  331 + }
  332 + /* Handle this via the gdb */
  333 + gdb_handlesig (env, SIGSEGV);
  334 + break;
  335 + case EXCP_PRIV:
  336 + fprintf(stderr, "Privilege violation\n");
  337 + if (loglevel)
  338 + fprintf(logfile, "Privilege violation\n");
  339 + info.si_signo = SIGILL;
  340 + info.si_errno = 0;
  341 + switch (env->error_code & 0xF) {
  342 + case EXCP_PRIV_OPC:
  343 + info.si_code = ILL_PRVOPC;
  344 + break;
  345 + case EXCP_PRIV_REG:
  346 + info.si_code = ILL_PRVREG;
  347 + break;
  348 + default:
  349 + fprintf(stderr, "Unknown privilege violation (%02x)\n",
  350 + env->error_code & 0xF);
  351 + info.si_code = ILL_PRVOPC;
  352 + break;
  353 + }
  354 + break;
  355 + case EXCP_TRAP:
  356 + fprintf(stderr, "Tried to call a TRAP\n");
  357 + if (loglevel)
  358 + fprintf(logfile, "Tried to call a TRAP\n");
  359 + abort();
  360 + default:
  361 + /* Should not happen ! */
  362 + fprintf(stderr, "Unknown program exception (%02x)\n",
  363 + env->error_code);
  364 + if (loglevel) {
  365 + fprintf(logfile, "Unknwon program exception (%02x)\n",
  366 + env->error_code);
  367 + }
  368 + abort();
  369 + }
  370 + info.si_addr = (void*)(env->nip - 4);
  371 + queue_signal(info.si_signo, &info);
  372 + break;
  373 + case EXCP_NO_FP:
  374 + fprintf(stderr, "No floating point allowed\n");
  375 + if (loglevel)
  376 + fprintf(logfile, "No floating point allowed\n");
  377 + info.si_signo = SIGILL;
  378 + info.si_errno = 0;
  379 + info.si_code = ILL_COPROC;
  380 + info.si_addr = (void*)(env->nip - 4);
  381 + queue_signal(info.si_signo, &info);
  382 + break;
  383 + case EXCP_DECR:
  384 + /* Should not happen ! */
  385 + fprintf(stderr, "Decrementer exception\n");
  386 + if (loglevel)
  387 + fprintf(logfile, "Decrementer exception\n");
  388 + abort();
  389 + case EXCP_TRACE:
  390 + /* Pass to gdb: we use this to trace execution */
  391 + gdb_handlesig (env, SIGTRAP);
  392 + break;
  393 + case EXCP_FP_ASSIST:
  394 + /* Should not happen ! */
  395 + fprintf(stderr, "Floating point assist exception\n");
  396 + if (loglevel)
  397 + fprintf(logfile, "Floating point assist exception\n");
  398 + abort();
  399 + case EXCP_MTMSR:
  400 + /* We reloaded the msr, just go on */
  401 + if (msr_pr == 0) {
  402 + fprintf(stderr, "Tried to go into supervisor mode !\n");
  403 + if (loglevel)
  404 + fprintf(logfile, "Tried to go into supervisor mode !\n");
  405 + abort();
  406 + }
  407 + break;
  408 + case EXCP_BRANCH:
  409 + /* We stopped because of a jump... */
  410 + break;
  411 + case EXCP_INTERRUPT:
  412 + /* Don't know why this should ever happen... */
  413 + fprintf(stderr, "EXCP_INTERRUPT\n");
  414 + break;
  415 + case EXCP_DEBUG:
  416 + gdb_handlesig (env, SIGTRAP);
  417 + break;
  418 + default:
  419 + fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
  420 + trapnr);
  421 + if (loglevel) {
  422 + fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
  423 + "0x%02x - aborting\n", trapnr, env->error_code);
  424 + }
  425 + abort();
  426 + }
  427 + process_pending_signals(env);
  428 + }
  429 +}
  430 +#endif
  431 +
  432 +
  433 +#ifdef TARGET_I386
  434 +
  435 +/***********************************************************/
  436 +/* CPUX86 core interface */
  437 +
  438 +uint64_t cpu_get_tsc(CPUX86State *env)
  439 +{
  440 + return cpu_get_real_ticks();
  441 +}
  442 +
  443 +void
  444 +write_dt(void *ptr, unsigned long addr, unsigned long limit,
  445 + int flags)
  446 +{
  447 + unsigned int e1, e2;
  448 + e1 = (addr << 16) | (limit & 0xffff);
  449 + e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000);
  450 + e2 |= flags;
  451 + stl((uint8_t *)ptr, e1);
  452 + stl((uint8_t *)ptr + 4, e2);
  453 +}
  454 +
  455 +static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
  456 + unsigned long addr, unsigned int sel)
  457 +{
  458 + unsigned int e1, e2;
  459 + e1 = (addr & 0xffff) | (sel << 16);
  460 + e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
  461 + stl((uint8_t *)ptr, e1);
  462 + stl((uint8_t *)ptr + 4, e2);
  463 +}
  464 +
  465 +#define GDT_TABLE_SIZE 14
  466 +#define LDT_TABLE_SIZE 15
  467 +#define IDT_TABLE_SIZE 256
  468 +#define TSS_SIZE 104
  469 +uint64_t gdt_table[GDT_TABLE_SIZE];
  470 +uint64_t ldt_table[LDT_TABLE_SIZE];
  471 +uint64_t idt_table[IDT_TABLE_SIZE];
  472 +uint32_t tss[TSS_SIZE];
  473 +
  474 +/* only dpl matters as we do only user space emulation */
  475 +static void set_idt(int n, unsigned int dpl)
  476 +{
  477 + set_gate(idt_table + n, 0, dpl, 0, 0);
  478 +}
  479 +
  480 +/* ABI convention: after a syscall if there was an error the CF flag is set */
  481 +static inline set_error(CPUX86State *env, int ret)
  482 +{
  483 + if(ret<0)
  484 + env->eflags = env->eflags | 0x1;
  485 + else
  486 + env->eflags &= ~0x1;
  487 + env->regs[R_EAX] = ret;
  488 +}
  489 +
  490 +void cpu_loop(CPUX86State *env)
  491 +{
  492 + int trapnr;
  493 + int ret;
  494 + uint8_t *pc;
  495 + target_siginfo_t info;
  496 +
  497 + for(;;) {
  498 + trapnr = cpu_x86_exec(env);
  499 + uint32_t *params = (uint32_t *)env->regs[R_ESP];
  500 + switch(trapnr) {
  501 + case 0x79: /* Our commpage hack back door exit is here */
  502 + do_commpage(env, env->eip, *(params + 1), *(params + 2),
  503 + *(params + 3), *(params + 4),
  504 + *(params + 5), *(params + 6),
  505 + *(params + 7), *(params + 8));
  506 + break;
  507 + case 0x81: /* mach syscall */
  508 + {
  509 + ret = do_mach_syscall(env, env->regs[R_EAX],
  510 + *(params + 1), *(params + 2),
  511 + *(params + 3), *(params + 4),
  512 + *(params + 5), *(params + 6),
  513 + *(params + 7), *(params + 8));
  514 + set_error(env, ret);
  515 + break;
  516 + }
  517 + case 0x90: /* unix backdoor */
  518 + {
  519 + /* after sysenter, stack is in R_ECX, new eip in R_EDX (sysexit will flip them back)*/
  520 + int saved_stack = env->regs[R_ESP];
  521 + env->regs[R_ESP] = env->regs[R_ECX];
  522 +
  523 + ret = do_unix_syscall(env, env->regs[R_EAX]);
  524 +
  525 + env->regs[R_ECX] = env->regs[R_ESP];
  526 + env->regs[R_ESP] = saved_stack;
  527 +
  528 + set_error(env, ret);
  529 + break;
  530 + }
  531 + case 0x80: /* unix syscall */
  532 + {
  533 + ret = do_unix_syscall(env, env->regs[R_EAX]/*,
  534 + *(params + 1), *(params + 2),
  535 + *(params + 3), *(params + 4),
  536 + *(params + 5), *(params + 6),
  537 + *(params + 7), *(params + 8)*/);
  538 + set_error(env, ret);
  539 + break;
  540 + }
  541 + case 0x82: /* thread syscall */
  542 + {
  543 + ret = do_thread_syscall(env, env->regs[R_EAX],
  544 + *(params + 1), *(params + 2),
  545 + *(params + 3), *(params + 4),
  546 + *(params + 5), *(params + 6),
  547 + *(params + 7), *(params + 8));
  548 + set_error(env, ret);
  549 + break;
  550 + }
  551 + case EXCP0B_NOSEG:
  552 + case EXCP0C_STACK:
  553 + info.si_signo = SIGBUS;
  554 + info.si_errno = 0;
  555 + info.si_code = BUS_NOOP;
  556 + info.si_addr = 0;
  557 + gdb_handlesig (env, SIGBUS);
  558 + queue_signal(info.si_signo, &info);
  559 + break;
  560 + case EXCP0D_GPF:
  561 + info.si_signo = SIGSEGV;
  562 + info.si_errno = 0;
  563 + info.si_code = SEGV_NOOP;
  564 + info.si_addr = 0;
  565 + gdb_handlesig (env, SIGSEGV);
  566 + queue_signal(info.si_signo, &info);
  567 + break;
  568 + case EXCP0E_PAGE:
  569 + info.si_signo = SIGSEGV;
  570 + info.si_errno = 0;
  571 + if (!(env->error_code & 1))
  572 + info.si_code = SEGV_MAPERR;
  573 + else
  574 + info.si_code = SEGV_ACCERR;
  575 + info.si_addr = (void*)env->cr[2];
  576 + gdb_handlesig (env, SIGSEGV);
  577 + queue_signal(info.si_signo, &info);
  578 + break;
  579 + case EXCP00_DIVZ:
  580 + /* division by zero */
  581 + info.si_signo = SIGFPE;
  582 + info.si_errno = 0;
  583 + info.si_code = FPE_INTDIV;
  584 + info.si_addr = (void*)env->eip;
  585 + gdb_handlesig (env, SIGFPE);
  586 + queue_signal(info.si_signo, &info);
  587 + break;
  588 + case EXCP01_SSTP:
  589 + case EXCP03_INT3:
  590 + info.si_signo = SIGTRAP;
  591 + info.si_errno = 0;
  592 + info.si_code = TRAP_BRKPT;
  593 + info.si_addr = (void*)env->eip;
  594 + gdb_handlesig (env, SIGTRAP);
  595 + queue_signal(info.si_signo, &info);
  596 + break;
  597 + case EXCP04_INTO:
  598 + case EXCP05_BOUND:
  599 + info.si_signo = SIGSEGV;
  600 + info.si_errno = 0;
  601 + info.si_code = SEGV_NOOP;
  602 + info.si_addr = 0;
  603 + gdb_handlesig (env, SIGSEGV);
  604 + queue_signal(info.si_signo, &info);
  605 + break;
  606 + case EXCP06_ILLOP:
  607 + info.si_signo = SIGILL;
  608 + info.si_errno = 0;
  609 + info.si_code = ILL_ILLOPN;
  610 + info.si_addr = (void*)env->eip;
  611 + gdb_handlesig (env, SIGILL);
  612 + queue_signal(info.si_signo, &info);
  613 + break;
  614 + case EXCP_INTERRUPT:
  615 + /* just indicate that signals should be handled asap */
  616 + break;
  617 + case EXCP_DEBUG:
  618 + {
  619 + int sig;
  620 +
  621 + sig = gdb_handlesig (env, SIGTRAP);
  622 + if (sig)
  623 + {
  624 + info.si_signo = sig;
  625 + info.si_errno = 0;
  626 + info.si_code = TRAP_BRKPT;
  627 + queue_signal(info.si_signo, &info);
  628 + }
  629 + }
  630 + break;
  631 + default:
  632 + pc = (void*)(env->segs[R_CS].base + env->eip);
  633 + fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
  634 + (long)pc, trapnr);
  635 + abort();
  636 + }
  637 + process_pending_signals(env);
  638 + }
  639 +}
  640 +#endif
  641 +
  642 +void usage(void)
  643 +{
  644 + printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
  645 + "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
  646 + "Darwin CPU emulator (compiled for %s emulation)\n"
  647 + "\n"
  648 + "-h print this help\n"
  649 + "-L path set the elf interpreter prefix (default=%s)\n"
  650 + "-s size set the stack size in bytes (default=%ld)\n"
  651 + "\n"
  652 + "debug options:\n"
  653 +#ifdef USE_CODE_COPY
  654 + "-no-code-copy disable code copy acceleration\n"
  655 +#endif
  656 + "-d options activate log (logfile=%s)\n"
  657 + "-g wait for gdb on port 1234\n"
  658 + "-p pagesize set the host page size to 'pagesize'\n",
  659 + TARGET_ARCH,
  660 + interp_prefix,
  661 + stack_size,
  662 + DEBUG_LOGFILE);
  663 + _exit(1);
  664 +}
  665 +
  666 +/* XXX: currently only used for async signals (see signal.c) */
  667 +CPUState *global_env;
  668 +/* used only if single thread */
  669 +CPUState *cpu_single_env = NULL;
  670 +
  671 +/* used to free thread contexts */
  672 +TaskState *first_task_state;
  673 +
  674 +int main(int argc, char **argv)
  675 +{
  676 + const char *filename;
  677 + struct target_pt_regs regs1, *regs = &regs1;
  678 + TaskState ts1, *ts = &ts1;
  679 + CPUState *env;
  680 + int optind;
  681 + short use_gdbstub = 0;
  682 + const char *r;
  683 +
  684 + if (argc <= 1)
  685 + usage();
  686 +
  687 + /* init debug */
  688 + cpu_set_log_filename(DEBUG_LOGFILE);
  689 +
  690 + optind = 1;
  691 + for(;;) {
  692 + if (optind >= argc)
  693 + break;
  694 + r = argv[optind];
  695 + if (r[0] != '-')
  696 + break;
  697 + optind++;
  698 + r++;
  699 + if (!strcmp(r, "-")) {
  700 + break;
  701 + } else if (!strcmp(r, "d")) {
  702 + int mask;
  703 + CPULogItem *item;
  704 +
  705 + if (optind >= argc)
  706 + break;
  707 +
  708 + r = argv[optind++];
  709 + mask = cpu_str_to_log_mask(r);
  710 + if (!mask) {
  711 + printf("Log items (comma separated):\n");
  712 + for(item = cpu_log_items; item->mask != 0; item++) {
  713 + printf("%-10s %s\n", item->name, item->help);
  714 + }
  715 + exit(1);
  716 + }
  717 + cpu_set_log(mask);
  718 + } else if (!strcmp(r, "s")) {
  719 + r = argv[optind++];
  720 + stack_size = strtol(r, (char **)&r, 0);
  721 + if (stack_size <= 0)
  722 + usage();
  723 + if (*r == 'M')
  724 + stack_size *= 1024 * 1024;
  725 + else if (*r == 'k' || *r == 'K')
  726 + stack_size *= 1024;
  727 + } else if (!strcmp(r, "L")) {
  728 + interp_prefix = argv[optind++];
  729 + } else if (!strcmp(r, "p")) {
  730 + qemu_host_page_size = atoi(argv[optind++]);
  731 + if (qemu_host_page_size == 0 ||
  732 + (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
  733 + fprintf(stderr, "page size must be a power of two\n");
  734 + exit(1);
  735 + }
  736 + } else
  737 + if (!strcmp(r, "g")) {
  738 + use_gdbstub = 1;
  739 + } else
  740 +#ifdef USE_CODE_COPY
  741 + if (!strcmp(r, "no-code-copy")) {
  742 + code_copy_enabled = 0;
  743 + } else
  744 +#endif
  745 + {
  746 + usage();
  747 + }
  748 + }
  749 + if (optind >= argc)
  750 + usage();
  751 + filename = argv[optind];
  752 +
  753 + /* Zero out regs */
  754 + memset(regs, 0, sizeof(struct target_pt_regs));
  755 +
  756 +#if 0
  757 + /* Scan interp_prefix dir for replacement files. */
  758 + init_paths(interp_prefix);
  759 +#endif
  760 +
  761 + /* NOTE: we need to init the CPU at this stage to get
  762 + qemu_host_page_size */
  763 + env = cpu_init();
  764 +
  765 + printf("Starting %s with qemu\n----------------\n", filename);
  766 +
  767 + commpage_init();
  768 +
  769 + if (mach_exec(filename, argv+optind, environ, regs) != 0) {
  770 + printf("Error loading %s\n", filename);
  771 + _exit(1);
  772 + }
  773 +
  774 + syscall_init();
  775 + signal_init();
  776 + global_env = env;
  777 +
  778 + /* build Task State */
  779 + memset(ts, 0, sizeof(TaskState));
  780 + env->opaque = ts;
  781 + ts->used = 1;
  782 + env->user_mode_only = 1;
  783 +
  784 +#if defined(TARGET_I386)
  785 + cpu_x86_set_cpl(env, 3);
  786 +
  787 + env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
  788 + env->hflags |= HF_PE_MASK;
  789 +
  790 + if (env->cpuid_features & CPUID_SSE) {
  791 + env->cr[4] |= CR4_OSFXSR_MASK;
  792 + env->hflags |= HF_OSFXSR_MASK;
  793 + }
  794 +
  795 + /* flags setup : we activate the IRQs by default as in user mode */
  796 + env->eflags |= IF_MASK;
  797 +
  798 + /* darwin register setup */
  799 + env->regs[R_EAX] = regs->eax;
  800 + env->regs[R_EBX] = regs->ebx;
  801 + env->regs[R_ECX] = regs->ecx;
  802 + env->regs[R_EDX] = regs->edx;
  803 + env->regs[R_ESI] = regs->esi;
  804 + env->regs[R_EDI] = regs->edi;
  805 + env->regs[R_EBP] = regs->ebp;
  806 + env->regs[R_ESP] = regs->esp;
  807 + env->eip = regs->eip;
  808 +
  809 + /* Darwin LDT setup */
  810 + /* 2 - User code segment
  811 + 3 - User data segment
  812 + 4 - User cthread */
  813 + bzero(ldt_table, LDT_TABLE_SIZE * sizeof(ldt_table[0]));
  814 + env->ldt.base = (uint32_t) ldt_table;
  815 + env->ldt.limit = sizeof(ldt_table) - 1;
  816 +
  817 + write_dt(ldt_table + 2, 0, 0xfffff,
  818 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  819 + (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT));
  820 + write_dt(ldt_table + 3, 0, 0xfffff,
  821 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  822 + (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
  823 + write_dt(ldt_table + 4, 0, 0xfffff,
  824 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  825 + (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
  826 +
  827 + /* Darwin GDT setup.
  828 + * has changed a lot between old Darwin/x86 (pre-Mac Intel) and Mac OS X/x86,
  829 + now everything is done via int 0x81(mach) int 0x82 (thread) and sysenter/sysexit(unix) */
  830 + bzero(gdt_table, sizeof(gdt_table));
  831 + env->gdt.base = (uint32_t)gdt_table;
  832 + env->gdt.limit = sizeof(gdt_table) - 1;
  833 +
  834 + /* Set up a back door to handle sysenter syscalls (unix) */
  835 + char * syscallbackdoor = malloc(64);
  836 + page_set_flags((int)syscallbackdoor, (int)syscallbackdoor + 64, PROT_EXEC | PROT_READ | PAGE_VALID);
  837 +
  838 + int i = 0;
  839 + syscallbackdoor[i++] = 0xcd;
  840 + syscallbackdoor[i++] = 0x90; /* int 0x90 */
  841 + syscallbackdoor[i++] = 0x0F;
  842 + syscallbackdoor[i++] = 0x35; /* sysexit */
  843 +
  844 + /* Darwin sysenter/sysexit setup */
  845 + env->sysenter_cs = 0x1; //XXX
  846 + env->sysenter_eip = (int)syscallbackdoor;
  847 + env->sysenter_esp = (int)malloc(64);
  848 +
  849 + /* Darwin TSS setup
  850 + This must match up with GDT[4] */
  851 + env->tr.base = (uint32_t) tss;
  852 + env->tr.limit = sizeof(tss) - 1;
  853 + env->tr.flags = DESC_P_MASK | (0x9 << DESC_TYPE_SHIFT);
  854 + stw(tss + 2, 0x10); // ss0 = 0x10 = GDT[2] = Kernel Data Segment
  855 +
  856 + /* Darwin interrupt setup */
  857 + bzero(idt_table, sizeof(idt_table));
  858 + env->idt.base = (uint32_t) idt_table;
  859 + env->idt.limit = sizeof(idt_table) - 1;
  860 + set_idt(0, 0);
  861 + set_idt(1, 0);
  862 + set_idt(2, 0);
  863 + set_idt(3, 3);
  864 + set_idt(4, 3);
  865 + set_idt(5, 3);
  866 + set_idt(6, 0);
  867 + set_idt(7, 0);
  868 + set_idt(8, 0);
  869 + set_idt(9, 0);
  870 + set_idt(10, 0);
  871 + set_idt(11, 0);
  872 + set_idt(12, 0);
  873 + set_idt(13, 0);
  874 + set_idt(14, 0);
  875 + set_idt(15, 0);
  876 + set_idt(16, 0);
  877 + set_idt(17, 0);
  878 + set_idt(18, 0);
  879 + set_idt(19, 0);
  880 + /* Syscalls are done via
  881 + int 0x80 (unix) (rarely used)
  882 + int 0x81 (mach)
  883 + int 0x82 (thread)
  884 + int 0x83 (diag) (not handled here)
  885 + sysenter/sysexit (unix) -> we redirect that to int 0x90 */
  886 + set_idt(0x79, 3); /* Commpage hack, here is our backdoor interrupt */
  887 + set_idt(0x80, 3); /* Unix Syscall */
  888 + set_idt(0x81, 3); /* Mach Syscalls */
  889 + set_idt(0x82, 3); /* thread Syscalls */
  890 +
  891 + set_idt(0x90, 3); /* Unix Syscall backdoor */
  892 +
  893 +
  894 + cpu_x86_load_seg(env, R_CS, __USER_CS);
  895 + cpu_x86_load_seg(env, R_DS, __USER_DS);
  896 + cpu_x86_load_seg(env, R_ES, __USER_DS);
  897 + cpu_x86_load_seg(env, R_SS, __USER_DS);
  898 + cpu_x86_load_seg(env, R_FS, __USER_DS);
  899 + cpu_x86_load_seg(env, R_GS, __USER_DS);
  900 +
  901 +#elif defined(TARGET_PPC)
  902 + {
  903 + int i;
  904 + env->nip = regs->nip;
  905 + for(i = 0; i < 32; i++) {
  906 + env->gpr[i] = regs->gpr[i];
  907 + }
  908 + }
  909 +#else
  910 +#error unsupported target CPU
  911 +#endif
  912 +
  913 + if (use_gdbstub) {
  914 + printf("Waiting for gdb Connection on port 1234...\n");
  915 + gdbserver_start (1234);
  916 + gdb_handlesig(env, 0);
  917 + }
  918 +
  919 + cpu_loop(env);
  920 + /* never exits */
  921 + return 0;
  922 +}
... ...
darwin-user/mmap.c 0 โ†’ 100644
  1 +/*
  2 + * mmap support for qemu
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include <stdlib.h>
  21 +#include <stdio.h>
  22 +#include <stdarg.h>
  23 +#include <string.h>
  24 +#include <unistd.h>
  25 +#include <errno.h>
  26 +#include <sys/mman.h>
  27 +
  28 +#include "qemu.h"
  29 +
  30 +//#define DEBUG_MMAP
  31 +
  32 +/* NOTE: all the constants are the HOST ones */
  33 +int target_mprotect(unsigned long start, unsigned long len, int prot)
  34 +{
  35 + unsigned long end, host_start, host_end, addr;
  36 + int prot1, ret;
  37 +
  38 +#ifdef DEBUG_MMAP
  39 + printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
  40 + prot & PROT_READ ? 'r' : '-',
  41 + prot & PROT_WRITE ? 'w' : '-',
  42 + prot & PROT_EXEC ? 'x' : '-');
  43 +#endif
  44 +
  45 + if ((start & ~TARGET_PAGE_MASK) != 0)
  46 + return -EINVAL;
  47 + len = TARGET_PAGE_ALIGN(len);
  48 + end = start + len;
  49 + if (end < start)
  50 + return -EINVAL;
  51 + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
  52 + return -EINVAL;
  53 + if (len == 0)
  54 + return 0;
  55 +
  56 + host_start = start & qemu_host_page_mask;
  57 + host_end = HOST_PAGE_ALIGN(end);
  58 + if (start > host_start) {
  59 + /* handle host page containing start */
  60 + prot1 = prot;
  61 + for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
  62 + prot1 |= page_get_flags(addr);
  63 + }
  64 + if (host_end == host_start + qemu_host_page_size) {
  65 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  66 + prot1 |= page_get_flags(addr);
  67 + }
  68 + end = host_end;
  69 + }
  70 + ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
  71 + if (ret != 0)
  72 + return ret;
  73 + host_start += qemu_host_page_size;
  74 + }
  75 + if (end < host_end) {
  76 + prot1 = prot;
  77 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  78 + prot1 |= page_get_flags(addr);
  79 + }
  80 + ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
  81 + prot1 & PAGE_BITS);
  82 + if (ret != 0)
  83 + return ret;
  84 + host_end -= qemu_host_page_size;
  85 + }
  86 +
  87 + /* handle the pages in the middle */
  88 + if (host_start < host_end) {
  89 + ret = mprotect((void *)host_start, host_end - host_start, prot);
  90 + if (ret != 0)
  91 + return ret;
  92 + }
  93 + page_set_flags(start, start + len, prot | PAGE_VALID);
  94 + return 0;
  95 +}
  96 +
  97 +/* map an incomplete host page */
  98 +int mmap_frag(unsigned long host_start,
  99 + unsigned long start, unsigned long end,
  100 + int prot, int flags, int fd, unsigned long offset)
  101 +{
  102 + unsigned long host_end, ret, addr;
  103 + int prot1, prot_new;
  104 +
  105 + host_end = host_start + qemu_host_page_size;
  106 +
  107 + /* get the protection of the target pages outside the mapping */
  108 + prot1 = 0;
  109 + for(addr = host_start; addr < host_end; addr++) {
  110 + if (addr < start || addr >= end)
  111 + prot1 |= page_get_flags(addr);
  112 + }
  113 +
  114 + if (prot1 == 0) {
  115 + /* no page was there, so we allocate one */
  116 + ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
  117 + flags | MAP_ANONYMOUS, -1, 0);
  118 + if (ret == -1)
  119 + return ret;
  120 + }
  121 + prot1 &= PAGE_BITS;
  122 +
  123 + prot_new = prot | prot1;
  124 + if (!(flags & MAP_ANONYMOUS)) {
  125 + /* msync() won't work here, so we return an error if write is
  126 + possible while it is a shared mapping */
  127 +#ifndef __APPLE__
  128 + if ((flags & MAP_TYPE) == MAP_SHARED &&
  129 +#else
  130 + if ((flags & MAP_SHARED) &&
  131 +#endif
  132 + (prot & PROT_WRITE))
  133 + return -EINVAL;
  134 +
  135 + /* adjust protection to be able to read */
  136 + if (!(prot1 & PROT_WRITE))
  137 + mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
  138 +
  139 + /* read the corresponding file data */
  140 + pread(fd, (void *)start, end - start, offset);
  141 +
  142 + /* put final protection */
  143 + if (prot_new != (prot1 | PROT_WRITE))
  144 + mprotect((void *)host_start, qemu_host_page_size, prot_new);
  145 + } else {
  146 + /* just update the protection */
  147 + if (prot_new != prot1) {
  148 + mprotect((void *)host_start, qemu_host_page_size, prot_new);
  149 + }
  150 + }
  151 + return 0;
  152 +}
  153 +
  154 +/* NOTE: all the constants are the HOST ones */
  155 +long target_mmap(unsigned long start, unsigned long len, int prot,
  156 + int flags, int fd, unsigned long offset)
  157 +{
  158 + unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
  159 +#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
  160 + static unsigned long last_start = 0x40000000;
  161 +#endif
  162 +
  163 +#ifdef DEBUG_MMAP
  164 + {
  165 + printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
  166 + start, len,
  167 + prot & PROT_READ ? 'r' : '-',
  168 + prot & PROT_WRITE ? 'w' : '-',
  169 + prot & PROT_EXEC ? 'x' : '-');
  170 + if (flags & MAP_FIXED)
  171 + printf("MAP_FIXED ");
  172 + if (flags & MAP_ANONYMOUS)
  173 + printf("MAP_ANON ");
  174 +#ifndef MAP_TYPE
  175 +# define MAP_TYPE 0x3
  176 +#endif
  177 + switch(flags & MAP_TYPE) {
  178 + case MAP_PRIVATE:
  179 + printf("MAP_PRIVATE ");
  180 + break;
  181 + case MAP_SHARED:
  182 + printf("MAP_SHARED ");
  183 + break;
  184 + default:
  185 + printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
  186 + break;
  187 + }
  188 + printf("fd=%d offset=%lx\n", fd, offset);
  189 + }
  190 +#endif
  191 +
  192 + if (offset & ~TARGET_PAGE_MASK)
  193 + return -EINVAL;
  194 +
  195 + len = TARGET_PAGE_ALIGN(len);
  196 + if (len == 0)
  197 + return start;
  198 + host_start = start & qemu_host_page_mask;
  199 +
  200 + if (!(flags & MAP_FIXED)) {
  201 +#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
  202 + /* tell the kenel to search at the same place as i386 */
  203 + if (host_start == 0) {
  204 + host_start = last_start;
  205 + last_start += HOST_PAGE_ALIGN(len);
  206 + }
  207 +#endif
  208 + if (qemu_host_page_size != qemu_real_host_page_size) {
  209 + /* NOTE: this code is only for debugging with '-p' option */
  210 + /* reserve a memory area */
  211 + host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
  212 + host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
  213 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  214 + if (host_start == -1)
  215 + return host_start;
  216 + host_end = host_start + host_len;
  217 + start = HOST_PAGE_ALIGN(host_start);
  218 + end = start + HOST_PAGE_ALIGN(len);
  219 + if (start > host_start)
  220 + munmap((void *)host_start, start - host_start);
  221 + if (end < host_end)
  222 + munmap((void *)end, host_end - end);
  223 + /* use it as a fixed mapping */
  224 + flags |= MAP_FIXED;
  225 + } else {
  226 + /* if not fixed, no need to do anything */
  227 + host_offset = offset & qemu_host_page_mask;
  228 + host_len = len + offset - host_offset;
  229 + start = (long)mmap((void *)host_start, host_len,
  230 + prot, flags, fd, host_offset);
  231 + if (start == -1)
  232 + return start;
  233 + /* update start so that it points to the file position at 'offset' */
  234 + if (!(flags & MAP_ANONYMOUS))
  235 + start += offset - host_offset;
  236 + goto the_end1;
  237 + }
  238 + }
  239 +
  240 + if (start & ~TARGET_PAGE_MASK)
  241 + return -EINVAL;
  242 + end = start + len;
  243 + host_end = HOST_PAGE_ALIGN(end);
  244 +
  245 + /* worst case: we cannot map the file because the offset is not
  246 + aligned, so we read it */
  247 + if (!(flags & MAP_ANONYMOUS) &&
  248 + (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
  249 + /* msync() won't work here, so we return an error if write is
  250 + possible while it is a shared mapping */
  251 +#ifndef __APPLE__
  252 + if ((flags & MAP_TYPE) == MAP_SHARED &&
  253 +#else
  254 + if ((flags & MAP_SHARED) &&
  255 +#endif
  256 + (prot & PROT_WRITE))
  257 + return -EINVAL;
  258 + retaddr = target_mmap(start, len, prot | PROT_WRITE,
  259 + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
  260 + -1, 0);
  261 + if (retaddr == -1)
  262 + return retaddr;
  263 + pread(fd, (void *)start, len, offset);
  264 + if (!(prot & PROT_WRITE)) {
  265 + ret = target_mprotect(start, len, prot);
  266 + if (ret != 0)
  267 + return ret;
  268 + }
  269 + goto the_end;
  270 + }
  271 +
  272 + /* handle the start of the mapping */
  273 + if (start > host_start) {
  274 + if (host_end == host_start + qemu_host_page_size) {
  275 + /* one single host page */
  276 + ret = mmap_frag(host_start, start, end,
  277 + prot, flags, fd, offset);
  278 + if (ret == -1)
  279 + return ret;
  280 + goto the_end1;
  281 + }
  282 + ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
  283 + prot, flags, fd, offset);
  284 + if (ret == -1)
  285 + return ret;
  286 + host_start += qemu_host_page_size;
  287 + }
  288 + /* handle the end of the mapping */
  289 + if (end < host_end) {
  290 + ret = mmap_frag(host_end - qemu_host_page_size,
  291 + host_end - qemu_host_page_size, host_end,
  292 + prot, flags, fd,
  293 + offset + host_end - qemu_host_page_size - start);
  294 + if (ret == -1)
  295 + return ret;
  296 + host_end -= qemu_host_page_size;
  297 + }
  298 +
  299 + /* map the middle (easier) */
  300 + if (host_start < host_end) {
  301 + unsigned long offset1;
  302 + if (flags & MAP_ANONYMOUS)
  303 + offset1 = 0;
  304 + else
  305 + offset1 = offset + host_start - start;
  306 + ret = (long)mmap((void *)host_start, host_end - host_start,
  307 + prot, flags, fd, offset1);
  308 + if (ret == -1)
  309 + return ret;
  310 + }
  311 + the_end1:
  312 + page_set_flags(start, start + len, prot | PAGE_VALID);
  313 + the_end:
  314 +#ifdef DEBUG_MMAP
  315 + printf("target_mmap: ret=0x%lx\n", (long)start);
  316 + page_dump(stdout);
  317 + printf("\n");
  318 +#endif
  319 + return start;
  320 +}
  321 +
  322 +int target_munmap(unsigned long start, unsigned long len)
  323 +{
  324 + unsigned long end, host_start, host_end, addr;
  325 + int prot, ret;
  326 +
  327 +#ifdef DEBUG_MMAP
  328 + printf("munmap: start=0x%lx len=0x%lx\n", start, len);
  329 +#endif
  330 + if (start & ~TARGET_PAGE_MASK)
  331 + return -EINVAL;
  332 + len = TARGET_PAGE_ALIGN(len);
  333 + if (len == 0)
  334 + return -EINVAL;
  335 + end = start + len;
  336 + host_start = start & qemu_host_page_mask;
  337 + host_end = HOST_PAGE_ALIGN(end);
  338 +
  339 + if (start > host_start) {
  340 + /* handle host page containing start */
  341 + prot = 0;
  342 + for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
  343 + prot |= page_get_flags(addr);
  344 + }
  345 + if (host_end == host_start + qemu_host_page_size) {
  346 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  347 + prot |= page_get_flags(addr);
  348 + }
  349 + end = host_end;
  350 + }
  351 + if (prot != 0)
  352 + host_start += qemu_host_page_size;
  353 + }
  354 + if (end < host_end) {
  355 + prot = 0;
  356 + for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
  357 + prot |= page_get_flags(addr);
  358 + }
  359 + if (prot != 0)
  360 + host_end -= qemu_host_page_size;
  361 + }
  362 +
  363 + /* unmap what we can */
  364 + if (host_start < host_end) {
  365 + ret = munmap((void *)host_start, host_end - host_start);
  366 + if (ret != 0)
  367 + return ret;
  368 + }
  369 +
  370 + page_set_flags(start, start + len, 0);
  371 + return 0;
  372 +}
  373 +
  374 +/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
  375 + blocks which have been allocated starting on a host page */
  376 +long target_mremap(unsigned long old_addr, unsigned long old_size,
  377 + unsigned long new_size, unsigned long flags,
  378 + unsigned long new_addr)
  379 +{
  380 +#ifndef __APPLE__
  381 + /* XXX: use 5 args syscall */
  382 + new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
  383 + if (new_addr == -1)
  384 + return new_addr;
  385 + prot = page_get_flags(old_addr);
  386 + page_set_flags(old_addr, old_addr + old_size, 0);
  387 + page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
  388 + return new_addr;
  389 +#else
  390 + qerror("target_mremap: unsupported\n");
  391 +#endif
  392 +
  393 +}
  394 +
  395 +int target_msync(unsigned long start, unsigned long len, int flags)
  396 +{
  397 + unsigned long end;
  398 +
  399 + if (start & ~TARGET_PAGE_MASK)
  400 + return -EINVAL;
  401 + len = TARGET_PAGE_ALIGN(len);
  402 + end = start + len;
  403 + if (end < start)
  404 + return -EINVAL;
  405 + if (end == start)
  406 + return 0;
  407 +
  408 + start &= qemu_host_page_mask;
  409 + return msync((void *)start, end - start, flags);
  410 +}
  411 +
... ...
darwin-user/qemu.h 0 โ†’ 100644
  1 +#ifndef GEMU_H
  2 +#define GEMU_H
  3 +
  4 +#include "thunk.h"
  5 +
  6 +#include <signal.h>
  7 +#include <string.h>
  8 +
  9 +#include "cpu.h"
  10 +
  11 +#include "gdbstub.h"
  12 +
  13 +typedef siginfo_t target_siginfo_t;
  14 +#define target_sigaction sigaction
  15 +#ifdef TARGET_I386
  16 +struct target_pt_regs {
  17 + long ebx;
  18 + long ecx;
  19 + long edx;
  20 + long esi;
  21 + long edi;
  22 + long ebp;
  23 + long eax;
  24 + int xds;
  25 + int xes;
  26 + long orig_eax;
  27 + long eip;
  28 + int xcs;
  29 + long eflags;
  30 + long esp;
  31 + int xss;
  32 +};
  33 +struct target_sigcontext {
  34 + int sc_onstack;
  35 + int sc_mask;
  36 + int sc_eax;
  37 + int sc_ebx;
  38 + int sc_ecx;
  39 + int sc_edx;
  40 + int sc_edi;
  41 + int sc_esi;
  42 + int sc_ebp;
  43 + int sc_esp;
  44 + int sc_ss;
  45 + int sc_eflags;
  46 + int sc_eip;
  47 + int sc_cs;
  48 + int sc_ds;
  49 + int sc_es;
  50 + int sc_fs;
  51 + int sc_gs;
  52 +};
  53 +
  54 +#define __USER_CS (0x17)
  55 +#define __USER_DS (0x1F)
  56 +
  57 +#elif defined(TARGET_PPC)
  58 +struct target_pt_regs {
  59 + unsigned long gpr[32];
  60 + unsigned long nip;
  61 + unsigned long msr;
  62 + unsigned long orig_gpr3; /* Used for restarting system calls */
  63 + unsigned long ctr;
  64 + unsigned long link;
  65 + unsigned long xer;
  66 + unsigned long ccr;
  67 + unsigned long mq; /* 601 only (not used at present) */
  68 + /* Used on APUS to hold IPL value. */
  69 + unsigned long trap; /* Reason for being here */
  70 + unsigned long dar; /* Fault registers */
  71 + unsigned long dsisr;
  72 + unsigned long result; /* Result of a system call */
  73 +};
  74 +
  75 +struct target_sigcontext {
  76 + int sc_onstack; /* sigstack state to restore */
  77 + int sc_mask; /* signal mask to restore */
  78 + int sc_ir; /* pc */
  79 + int sc_psw; /* processor status word */
  80 + int sc_sp; /* stack pointer if sc_regs == NULL */
  81 + void *sc_regs; /* (kernel private) saved state */
  82 +};
  83 +
  84 +#endif
  85 +
  86 +typedef struct TaskState {
  87 + struct TaskState *next;
  88 + int used; /* non zero if used */
  89 + uint8_t stack[0];
  90 +} __attribute__((aligned(16))) TaskState;
  91 +
  92 +void syscall_init(void);
  93 +long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  94 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
  95 +long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  96 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
  97 +long do_unix_syscall(void *cpu_env, int num);
  98 +int do_sigaction(int sig, const struct sigaction *act,
  99 + struct sigaction *oact);
  100 +int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
  101 +
  102 +void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
  103 +void qerror(const char *fmt, ...);
  104 +
  105 +void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
  106 +
  107 +extern CPUState *global_env;
  108 +void cpu_loop(CPUState *env);
  109 +void init_paths(const char *prefix);
  110 +const char *path(const char *pathname);
  111 +
  112 +extern int loglevel;
  113 +extern FILE *logfile;
  114 +
  115 +/* commpage.c */
  116 +void commpage_init();
  117 +void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  118 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
  119 +
  120 +/* signal.c */
  121 +void process_pending_signals(void *cpu_env);
  122 +void signal_init(void);
  123 +int queue_signal(int sig, target_siginfo_t *info);
  124 +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
  125 +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
  126 +long do_sigreturn(CPUState *env, int num);
  127 +
  128 +/* machload.c */
  129 +int mach_exec(const char * filename, char ** argv, char ** envp,
  130 + struct target_pt_regs * regs);
  131 +
  132 +/* mmap.c */
  133 +int target_mprotect(unsigned long start, unsigned long len, int prot);
  134 +long target_mmap(unsigned long start, unsigned long len, int prot,
  135 + int flags, int fd, unsigned long offset);
  136 +int target_munmap(unsigned long start, unsigned long len);
  137 +long target_mremap(unsigned long old_addr, unsigned long old_size,
  138 + unsigned long new_size, unsigned long flags,
  139 + unsigned long new_addr);
  140 +int target_msync(unsigned long start, unsigned long len, int flags);
  141 +
  142 +/* user access */
  143 +
  144 +/* XXX: todo protect every memory access */
  145 +#define lock_user(x,y,z) (void*)(x)
  146 +#define unlock_user(x,y,z)
  147 +
  148 +/* Mac OS X ABI arguments processing */
  149 +#ifdef TARGET_I386
  150 +static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
  151 +{
  152 + uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
  153 + *i+=4;
  154 + return tswap32(*args);
  155 +}
  156 +static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
  157 +{
  158 + uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
  159 + *i+=8;
  160 + return tswap64(*args);
  161 +}
  162 +#elif defined(TARGET_PPC)
  163 +static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
  164 +{
  165 + /* XXX: won't work when args goes on stack after gpr10 */
  166 + uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
  167 + *i+=4;
  168 + return tswap32(args);
  169 +}
  170 +static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
  171 +{
  172 + /* XXX: won't work when args goes on stack after gpr10 */
  173 + uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
  174 + *i+=(8 << 8) + 8;
  175 + return tswap64(args);
  176 +}
  177 +#endif
  178 +
  179 +#endif
... ...
darwin-user/signal.c 0 โ†’ 100644
  1 +/*
  2 + * Emulation of Linux signals
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include <stdlib.h>
  21 +#include <stdio.h>
  22 +#include <string.h>
  23 +#include <stdarg.h>
  24 +#include <unistd.h>
  25 +#include <signal.h>
  26 +#include <errno.h>
  27 +#include <sys/ucontext.h>
  28 +
  29 +#ifdef __ia64__
  30 +#undef uc_mcontext
  31 +#undef uc_sigmask
  32 +#undef uc_stack
  33 +#undef uc_link
  34 +#endif
  35 +
  36 +#include <signal.h>
  37 +
  38 +#include "qemu.h"
  39 +
  40 +#define DEBUG_SIGNAL
  41 +
  42 +#define MAX_SIGQUEUE_SIZE 1024
  43 +
  44 +struct sigqueue {
  45 + struct sigqueue *next;
  46 + target_siginfo_t info;
  47 +};
  48 +
  49 +struct emulated_sigaction {
  50 + struct target_sigaction sa;
  51 + int pending; /* true if signal is pending */
  52 + struct sigqueue *first;
  53 + struct sigqueue info; /* in order to always have memory for the
  54 + first signal, we put it here */
  55 +};
  56 +
  57 +struct sigaltstack target_sigaltstack_used = {
  58 + 0, 0, SA_DISABLE
  59 +};
  60 +
  61 +static struct emulated_sigaction sigact_table[NSIG];
  62 +static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
  63 +static struct sigqueue *first_free; /* first free siginfo queue entry */
  64 +static int signal_pending; /* non zero if a signal may be pending */
  65 +
  66 +static void host_signal_handler(int host_signum, siginfo_t *info,
  67 + void *puc);
  68 +
  69 +
  70 +static inline int host_to_target_signal(int sig)
  71 +{
  72 + return sig;
  73 +}
  74 +
  75 +static inline int target_to_host_signal(int sig)
  76 +{
  77 + return sig;
  78 +}
  79 +
  80 +/* siginfo conversion */
  81 +
  82 +
  83 +
  84 +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
  85 +{
  86 +
  87 +}
  88 +
  89 +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
  90 +{
  91 +
  92 +}
  93 +
  94 +void signal_init(void)
  95 +{
  96 + struct sigaction act;
  97 + int i;
  98 +
  99 + /* set all host signal handlers. ALL signals are blocked during
  100 + the handlers to serialize them. */
  101 + sigfillset(&act.sa_mask);
  102 + act.sa_flags = SA_SIGINFO;
  103 + act.sa_sigaction = host_signal_handler;
  104 + for(i = 1; i < NSIG; i++) {
  105 + sigaction(i, &act, NULL);
  106 + }
  107 +
  108 + memset(sigact_table, 0, sizeof(sigact_table));
  109 +
  110 + first_free = &sigqueue_table[0];
  111 + for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
  112 + sigqueue_table[i].next = &sigqueue_table[i + 1];
  113 + sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
  114 +}
  115 +
  116 +/* signal queue handling */
  117 +
  118 +static inline struct sigqueue *alloc_sigqueue(void)
  119 +{
  120 + struct sigqueue *q = first_free;
  121 + if (!q)
  122 + return NULL;
  123 + first_free = q->next;
  124 + return q;
  125 +}
  126 +
  127 +static inline void free_sigqueue(struct sigqueue *q)
  128 +{
  129 + q->next = first_free;
  130 + first_free = q;
  131 +}
  132 +
  133 +/* abort execution with signal */
  134 +void __attribute((noreturn)) force_sig(int sig)
  135 +{
  136 + int host_sig;
  137 + host_sig = target_to_host_signal(sig);
  138 + fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
  139 + sig, strsignal(host_sig));
  140 + _exit(-host_sig);
  141 +}
  142 +
  143 +/* queue a signal so that it will be send to the virtual CPU as soon
  144 + as possible */
  145 +int queue_signal(int sig, target_siginfo_t *info)
  146 +{
  147 + struct emulated_sigaction *k;
  148 + struct sigqueue *q, **pq;
  149 + target_ulong handler;
  150 +
  151 +#if defined(DEBUG_SIGNAL)
  152 + fprintf(stderr, "queue_signal: sig=%d\n",
  153 + sig);
  154 +#endif
  155 + k = &sigact_table[sig - 1];
  156 + handler = (target_ulong)k->sa.sa_handler;
  157 + if (handler == SIG_DFL) {
  158 + /* default handler : ignore some signal. The other are fatal */
  159 + if (sig != SIGCHLD &&
  160 + sig != SIGURG &&
  161 + sig != SIGWINCH) {
  162 + force_sig(sig);
  163 + } else {
  164 + return 0; /* indicate ignored */
  165 + }
  166 + } else if (handler == host_to_target_signal(SIG_IGN)) {
  167 + /* ignore signal */
  168 + return 0;
  169 + } else if (handler == host_to_target_signal(SIG_ERR)) {
  170 + force_sig(sig);
  171 + } else {
  172 + pq = &k->first;
  173 + if (!k->pending) {
  174 + /* first signal */
  175 + q = &k->info;
  176 + } else {
  177 + q = alloc_sigqueue();
  178 + if (!q)
  179 + return -EAGAIN;
  180 + while (*pq != NULL)
  181 + pq = &(*pq)->next;
  182 + }
  183 + *pq = q;
  184 + q->info = *info;
  185 + q->next = NULL;
  186 + k->pending = 1;
  187 + /* signal that a new signal is pending */
  188 + signal_pending = 1;
  189 + return 1; /* indicates that the signal was queued */
  190 + }
  191 +}
  192 +
  193 +static void host_signal_handler(int host_signum, siginfo_t *info,
  194 + void *puc)
  195 +{
  196 + int sig;
  197 + target_siginfo_t tinfo;
  198 +
  199 + /* the CPU emulator uses some host signals to detect exceptions,
  200 + we we forward to it some signals */
  201 + if (host_signum == SIGSEGV || host_signum == SIGBUS
  202 +#if defined(TARGET_I386) && defined(USE_CODE_COPY)
  203 + || host_signum == SIGFPE
  204 +#endif
  205 + ) {
  206 + if (cpu_signal_handler(host_signum, (void*)info, puc))
  207 + return;
  208 + }
  209 +
  210 + /* get target signal number */
  211 + sig = host_to_target_signal(host_signum);
  212 + if (sig < 1 || sig > NSIG)
  213 + return;
  214 +
  215 +#if defined(DEBUG_SIGNAL)
  216 + fprintf(stderr, "qemu: got signal %d\n", sig);
  217 +#endif
  218 + if (queue_signal(sig, &tinfo) == 1) {
  219 + /* interrupt the virtual CPU as soon as possible */
  220 + cpu_interrupt(global_env, CPU_INTERRUPT_EXIT);
  221 + }
  222 +}
  223 +
  224 +int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
  225 +{
  226 + /* XXX: test errors */
  227 + if(oss)
  228 + {
  229 + oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
  230 + oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
  231 + oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
  232 + }
  233 + if(ss)
  234 + {
  235 + target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
  236 + target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
  237 + target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
  238 + }
  239 + return 0;
  240 +}
  241 +
  242 +int do_sigaction(int sig, const struct sigaction *act,
  243 + struct sigaction *oact)
  244 +{
  245 + struct emulated_sigaction *k;
  246 + struct sigaction act1;
  247 + int host_sig;
  248 +
  249 + if (sig < 1 || sig > NSIG)
  250 + return -EINVAL;
  251 +
  252 + k = &sigact_table[sig - 1];
  253 +#if defined(DEBUG_SIGNAL)
  254 + fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
  255 + sig, (int)act, (int)oact);
  256 +#endif
  257 + if (oact) {
  258 +#if defined(DEBUG_SIGNAL)
  259 + fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
  260 + sig, (int)act, (int)oact);
  261 +#endif
  262 +
  263 + oact->sa_handler = tswapl(k->sa.sa_handler);
  264 + oact->sa_flags = tswapl(k->sa.sa_flags);
  265 + oact->sa_mask = tswapl(k->sa.sa_mask);
  266 + }
  267 + if (act) {
  268 +#if defined(DEBUG_SIGNAL)
  269 + fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
  270 + act->sa_handler, act->sa_flags, act->sa_mask);
  271 +#endif
  272 +
  273 + k->sa.sa_handler = tswapl(act->sa_handler);
  274 + k->sa.sa_flags = tswapl(act->sa_flags);
  275 + k->sa.sa_mask = tswapl(act->sa_mask);
  276 + /* we update the host signal state */
  277 + host_sig = target_to_host_signal(sig);
  278 + if (host_sig != SIGSEGV && host_sig != SIGBUS) {
  279 +#if defined(DEBUG_SIGNAL)
  280 + fprintf(stderr, "sigaction handler going to call sigaction\n",
  281 + act->sa_handler, act->sa_flags, act->sa_mask);
  282 +#endif
  283 +
  284 + sigfillset(&act1.sa_mask);
  285 + act1.sa_flags = SA_SIGINFO;
  286 + if (k->sa.sa_flags & SA_RESTART)
  287 + act1.sa_flags |= SA_RESTART;
  288 + /* NOTE: it is important to update the host kernel signal
  289 + ignore state to avoid getting unexpected interrupted
  290 + syscalls */
  291 + if (k->sa.sa_handler == SIG_IGN) {
  292 + act1.sa_sigaction = (void *)SIG_IGN;
  293 + } else if (k->sa.sa_handler == SIG_DFL) {
  294 + act1.sa_sigaction = (void *)SIG_DFL;
  295 + } else {
  296 + act1.sa_sigaction = host_signal_handler;
  297 + }
  298 + sigaction(host_sig, &act1, NULL);
  299 + }
  300 + }
  301 + return 0;
  302 +}
  303 +
  304 +
  305 +#ifdef TARGET_I386
  306 +
  307 +static inline void *
  308 +get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
  309 +{
  310 + /* XXX Fix that */
  311 + if(target_sigaltstack_used.ss_flags & SA_DISABLE)
  312 + {
  313 + int esp;
  314 + /* Default to using normal stack */
  315 + esp = env->regs[R_ESP];
  316 +
  317 + return (void *)((esp - frame_size) & -8ul);
  318 + }
  319 + else
  320 + {
  321 + return target_sigaltstack_used.ss_sp;
  322 + }
  323 +}
  324 +
  325 +static void setup_frame(int sig, struct emulated_sigaction *ka,
  326 + void *set, CPUState *env)
  327 +{
  328 + void *frame;
  329 + int i, err = 0;
  330 +
  331 + fprintf(stderr, "setup_frame %d\n", sig);
  332 + frame = get_sigframe(ka, env, sizeof(*frame));
  333 +
  334 + /* Set up registers for signal handler */
  335 + env->regs[R_ESP] = (unsigned long) frame;
  336 + env->eip = (unsigned long) ka->sa.sa_handler;
  337 +
  338 + env->eflags &= ~TF_MASK;
  339 +
  340 + return;
  341 +
  342 +give_sigsegv:
  343 + if (sig == SIGSEGV)
  344 + ka->sa.sa_handler = SIG_DFL;
  345 + force_sig(SIGSEGV /* , current */);
  346 +}
  347 +
  348 +long do_sigreturn(CPUState *env, int num)
  349 +{
  350 + int i = 0;
  351 + struct target_sigcontext *scp = get_int_arg(&i, env);
  352 + /* XXX Get current signal number */
  353 + /* XXX Adjust accordin to sc_onstack, sc_mask */
  354 + if(tswapl(scp->sc_onstack) & 0x1)
  355 + target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
  356 + else
  357 + target_sigaltstack_used.ss_flags &= SA_DISABLE;
  358 + int set = tswapl(scp->sc_eax);
  359 + sigprocmask(SIG_SETMASK, &set, NULL);
  360 +
  361 + fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
  362 + fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
  363 + fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
  364 +
  365 + env->regs[R_EAX] = tswapl(scp->sc_eax);
  366 + env->regs[R_EBX] = tswapl(scp->sc_ebx);
  367 + env->regs[R_ECX] = tswapl(scp->sc_ecx);
  368 + env->regs[R_EDX] = tswapl(scp->sc_edx);
  369 + env->regs[R_EDI] = tswapl(scp->sc_edi);
  370 + env->regs[R_ESI] = tswapl(scp->sc_esi);
  371 + env->regs[R_EBP] = tswapl(scp->sc_ebp);
  372 + env->regs[R_ESP] = tswapl(scp->sc_esp);
  373 + env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
  374 + env->eflags = tswapl(scp->sc_eflags);
  375 + env->eip = tswapl(scp->sc_eip);
  376 + env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
  377 + env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
  378 + env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
  379 + env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
  380 + env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
  381 +
  382 + /* Again, because our caller's caller will reset EAX */
  383 + return env->regs[R_EAX];
  384 +}
  385 +
  386 +#else
  387 +
  388 +static void setup_frame(int sig, struct emulated_sigaction *ka,
  389 + void *set, CPUState *env)
  390 +{
  391 + fprintf(stderr, "setup_frame: not implemented\n");
  392 +}
  393 +
  394 +long do_sigreturn(CPUState *env, int num)
  395 +{
  396 + int i = 0;
  397 + struct target_sigcontext *scp = get_int_arg(&i, env);
  398 + fprintf(stderr, "do_sigreturn: not implemented\n");
  399 + return -ENOSYS;
  400 +}
  401 +
  402 +#endif
  403 +
  404 +void process_pending_signals(void *cpu_env)
  405 +{
  406 + struct emulated_sigaction *k;
  407 + struct sigqueue *q;
  408 + target_ulong handler;
  409 + int sig;
  410 +
  411 + if (!signal_pending)
  412 + return;
  413 +
  414 + k = sigact_table;
  415 +
  416 + for(sig = 1; sig <= NSIG; sig++) {
  417 + if (k->pending)
  418 + goto handle_signal;
  419 + k++;
  420 + }
  421 +
  422 + /* if no signal is pending, just return */
  423 + signal_pending = 0;
  424 + return;
  425 +handle_signal:
  426 + #ifdef DEBUG_SIGNAL
  427 + fprintf(stderr, "qemu: process signal %d\n", sig);
  428 + #endif
  429 + /* dequeue signal */
  430 + q = k->first;
  431 + k->first = q->next;
  432 + if (!k->first)
  433 + k->pending = 0;
  434 +
  435 + sig = gdb_handlesig (cpu_env, sig);
  436 + if (!sig) {
  437 + fprintf (stderr, "Lost signal\n");
  438 + abort();
  439 + }
  440 +
  441 + handler = k->sa.sa_handler;
  442 + if (handler == SIG_DFL) {
  443 + /* default handler : ignore some signal. The other are fatal */
  444 + if (sig != SIGCHLD &&
  445 + sig != SIGURG &&
  446 + sig != SIGWINCH) {
  447 + force_sig(sig);
  448 + }
  449 + } else if (handler == SIG_IGN) {
  450 + /* ignore sig */
  451 + } else if (handler == SIG_ERR) {
  452 + force_sig(sig);
  453 + } else {
  454 +
  455 + setup_frame(sig, k, 0, cpu_env);
  456 + if (k->sa.sa_flags & SA_RESETHAND)
  457 + k->sa.sa_handler = SIG_DFL;
  458 + }
  459 + if (q != &k->info)
  460 + free_sigqueue(q);
  461 +}
  462 +
  463 +
... ...
darwin-user/syscall.c 0 โ†’ 100644
  1 +/*
  2 + * Darwin syscalls
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + * Copyright (c) 2006 Pierre d'Herbemont
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 + */
  21 +#include <fcntl.h>
  22 +#include <stdio.h>
  23 +#include <stdlib.h>
  24 +#include <errno.h>
  25 +
  26 +#include <mach/message.h>
  27 +#include <mach/mach.h>
  28 +#include <mach/mach_time.h>
  29 +
  30 +#include <pthread.h>
  31 +#include <dirent.h>
  32 +
  33 +#include <sys/stat.h>
  34 +#include <sys/syscall.h>
  35 +#include <sys/sysctl.h>
  36 +#include <sys/types.h>
  37 +#include <unistd.h>
  38 +#include <sys/ioctl.h>
  39 +#include <sys/mman.h>
  40 +#include <sys/types.h>
  41 +#include <sys/dirent.h>
  42 +#include <sys/uio.h>
  43 +#include <sys/termios.h>
  44 +#include <sys/ptrace.h>
  45 +#include <net/if.h>
  46 +
  47 +#include <sys/param.h>
  48 +#include <sys/mount.h>
  49 +
  50 +#include <sys/attr.h>
  51 +
  52 +#include <mach/ndr.h>
  53 +#include <mach/mig_errors.h>
  54 +
  55 +#include "qemu.h"
  56 +
  57 +//#define DEBUG_SYSCALL
  58 +
  59 +#ifdef DEBUG_SYSCALL
  60 +# define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
  61 +# define DEBUG_BEGIN_ENABLE __DEBUG_qemu_user_force_enable = 1;
  62 +# define DEBUG_END_ENABLE __DEBUG_qemu_user_force_enable = 0;
  63 +
  64 +# define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
  65 +# define DEBUG_ENABLE_ALL() static int __DEBUG_qemu_user_force_enable = 1
  66 + DEBUG_ENABLE_ALL();
  67 +
  68 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
  69 + if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
  70 + } while(0)
  71 +#else
  72 +# define DEBUG_FORCE_ENABLE_LOCAL()
  73 +# define DEBUG_BEGIN_ENABLE
  74 +# define DEBUG_END_ENABLE
  75 +
  76 +# define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
  77 +#endif
  78 +
  79 +enum {
  80 + bswap_out = 0,
  81 + bswap_in = 1
  82 +};
  83 +
  84 +extern const char *interp_prefix;
  85 +
  86 +static inline long get_errno(long ret)
  87 +{
  88 + if (ret == -1)
  89 + return -errno;
  90 + else
  91 + return ret;
  92 +}
  93 +
  94 +static inline int is_error(long ret)
  95 +{
  96 + return (unsigned long)ret >= (unsigned long)(-4096);
  97 +}
  98 +
  99 +/* ------------------------------------------------------------
  100 + Mach syscall handling
  101 +*/
  102 +
  103 +void static inline print_description_msg_header(mach_msg_header_t *hdr)
  104 +{
  105 + char *name = NULL;
  106 + int i;
  107 + struct { int number; char *name; } msg_name[] =
  108 + {
  109 + /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
  110 + { 200, "host_info" },
  111 + { 202, "host_page_size" },
  112 + { 206, "host_get_clock_service" },
  113 + { 206, "host_get_clock_service" },
  114 + { 206, "host_get_clock_service" },
  115 + { 306, "host_get_clock_service" },
  116 + { 3204, "mach_port_allocate" },
  117 + { 3206, "mach_port_deallocate" },
  118 + { 3404, "mach_ports_lookup" },
  119 + { 3409, "mach_task_get_special_port" },
  120 + { 3414, "mach_task_get_exception_ports" },
  121 + { 3418, "mach_semaphore_create" },
  122 + { 3504, "mach_semaphore_create" },
  123 + { 3509, "mach_semaphore_create" },
  124 + { 3518, "semaphore_create" },
  125 + { 3616, "thread_policy" },
  126 + { 3801, "vm_allocate" },
  127 + { 3802, "vm_deallocate" },
  128 + { 3802, "vm_deallocate" },
  129 + { 3803, "vm_protect" },
  130 + { 3812, "vm_map" },
  131 + { 4241776, "lu_message_send_id" }, /* lookupd */
  132 + { 4241876, "lu_message_reply_id" }, /* lookupd */
  133 + };
  134 +
  135 + for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
  136 + if(msg_name[i].number == hdr->msgh_id)
  137 + {
  138 + name = msg_name[i].name;
  139 + break;
  140 + }
  141 + }
  142 + if(!name)
  143 + DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
  144 + else
  145 + DPRINTF("%s\n", name);
  146 +#if 0
  147 + DPRINTF("Bits: %8x\n", hdr->msgh_bits);
  148 + DPRINTF("Size: %8x\n", hdr->msgh_size);
  149 + DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
  150 + DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
  151 + DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
  152 +
  153 + DPRINTF("Id : %8x\n", hdr->msgh_id);
  154 +
  155 + NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
  156 + DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
  157 + DPRINTF("%d %d %d %d %d %d %d %d\n",
  158 + ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
  159 + ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
  160 +#endif
  161 +}
  162 +
  163 +static inline void print_mach_msg_return(mach_msg_return_t ret)
  164 +{
  165 + int i, found = 0;
  166 +#define MACH_MSG_RET(msg) { msg, #msg }
  167 + struct { int code; char *name; } msg_name[] =
  168 + {
  169 + /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
  170 + /* send message */
  171 + MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
  172 + MACH_MSG_RET(MACH_SEND_NO_BUFFER),
  173 + MACH_MSG_RET(MACH_SEND_INVALID_DATA),
  174 + MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
  175 + MACH_MSG_RET(MACH_SEND_INVALID_DEST),
  176 + MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
  177 + MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
  178 + MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
  179 + MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
  180 + MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
  181 + MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
  182 + MACH_MSG_RET(MACH_SEND_INTERRUPTED),
  183 + MACH_MSG_RET(MACH_SEND_TIMED_OUT),
  184 +
  185 + MACH_MSG_RET(MACH_RCV_BODY_ERROR),
  186 + MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
  187 +
  188 + MACH_MSG_RET(MACH_RCV_IN_SET),
  189 + MACH_MSG_RET(MACH_RCV_INTERRUPTED),
  190 +
  191 + MACH_MSG_RET(MACH_RCV_INVALID_DATA),
  192 + MACH_MSG_RET(MACH_RCV_INVALID_NAME),
  193 + MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
  194 + MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
  195 + MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
  196 +
  197 + MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
  198 + MACH_MSG_RET(MACH_RCV_PORT_DIED),
  199 +
  200 + MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
  201 + MACH_MSG_RET(MACH_RCV_TIMED_OUT),
  202 + MACH_MSG_RET(MACH_RCV_TOO_LARGE)
  203 + };
  204 +#undef MACH_MSG_RET
  205 +
  206 + if( ret == MACH_MSG_SUCCESS)
  207 + DPRINTF("MACH_MSG_SUCCESS\n");
  208 + else
  209 + {
  210 + for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
  211 + if(msg_name[0].code & ret) {
  212 + DPRINTF("%s ", msg_name[0].name);
  213 + found = 1;
  214 + }
  215 + }
  216 + if(!found)
  217 + qerror("unknow mach message ret code %d\n", ret);
  218 + else
  219 + DPRINTF("\n");
  220 + }
  221 +}
  222 +
  223 +static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
  224 +{
  225 + hdr->msgh_bits = tswap32(hdr->msgh_bits);
  226 + hdr->msgh_size = tswap32(hdr->msgh_size);
  227 + hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
  228 + hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
  229 + hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
  230 + hdr->msgh_id = tswap32(hdr->msgh_id);
  231 +}
  232 +
  233 +struct complex_msg {
  234 + mach_msg_header_t hdr;
  235 + mach_msg_body_t body;
  236 +};
  237 +
  238 +static inline void * swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
  239 +{
  240 + mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
  241 + int i,j;
  242 + void *additional_data;
  243 +
  244 + if(bswap == bswap_in)
  245 + tswap32s(&complex_msg->body.msgh_descriptor_count);
  246 +
  247 + DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
  248 +
  249 + for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
  250 + switch(descr->type)
  251 + {
  252 + case MACH_MSG_PORT_DESCRIPTOR:
  253 + tswap32s(&descr->name);
  254 + descr++;
  255 + break;
  256 + case MACH_MSG_OOL_DESCRIPTOR:
  257 + {
  258 + mach_msg_ool_descriptor_t *ool = (void *)descr;
  259 + tswap32s((uint32_t *)&ool->address);
  260 + tswap32s(&ool->size);
  261 +
  262 + descr = (mach_msg_port_descriptor_t *)(ool+1);
  263 + break;
  264 + }
  265 + case MACH_MSG_OOL_PORTS_DESCRIPTOR:
  266 + {
  267 + mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
  268 + mach_port_name_t * port_names;
  269 +
  270 + if(bswap == bswap_in)
  271 + {
  272 + tswap32s((uint32_t *)&ool_ports->address);
  273 + tswap32s(&ool_ports->count);
  274 + }
  275 +
  276 + port_names = ool_ports->address;
  277 +
  278 + for(j = 0; j < ool_ports->count; j++)
  279 + tswap32s(&port_names[j]);
  280 +
  281 + if(bswap == bswap_out)
  282 + {
  283 + tswap32s((uint32_t *)&ool_ports->address);
  284 + tswap32s(&ool_ports->count);
  285 + }
  286 +
  287 + descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
  288 + break;
  289 + }
  290 + default: qerror("unknow mach msg descriptor type %x\n", descr->type);
  291 + }
  292 + }
  293 + if(bswap == bswap_out)
  294 + tswap32s(&complex_msg->body.msgh_descriptor_count);
  295 + additional_data = descr;
  296 + return additional_data;
  297 +}
  298 +
  299 +static inline uint32_t target_mach_msg_trap(
  300 + mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
  301 + uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify )
  302 +{
  303 + extern int mach_msg_trap(mach_msg_header_t *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
  304 + mach_msg_audit_trailer_t *trailer;
  305 + mach_msg_id_t msg_id;
  306 + uint32_t ret = 0;
  307 + char *additional_data;
  308 + int i;
  309 +
  310 + swap_mach_msg_header(hdr);
  311 +
  312 + print_description_msg_header(hdr);
  313 +
  314 + msg_id = hdr->msgh_id;
  315 +
  316 + if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
  317 + additional_data = swap_mach_msg_body((struct complex_msg *)hdr, bswap_in);
  318 + else
  319 + additional_data = (void*)(hdr+1);
  320 +
  321 + ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
  322 +
  323 + print_mach_msg_return(ret);
  324 +
  325 + if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
  326 + additional_data = swap_mach_msg_body((struct complex_msg *)hdr, bswap_out);
  327 + else
  328 + additional_data = (void*)(hdr+1);
  329 +
  330 + if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
  331 + {
  332 + /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
  333 + probably always bswap it */
  334 + /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
  335 + natural_t units but according to xnu/osfmk/mach/message.h: "The size of
  336 + the message must be specified in bytes" */
  337 + trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
  338 + /* XXX: Should probably do that based on the option asked by the sender, but dealing
  339 + with kernel answer seems more sound */
  340 + switch(trailer->msgh_trailer_size)
  341 + {
  342 + case sizeof(mach_msg_audit_trailer_t):
  343 + for(i = 0; i < 8; i++)
  344 + tswap32s(&trailer->msgh_audit.val[i]);
  345 + /* Fall in mach_msg_security_trailer_t case */
  346 + case sizeof(mach_msg_security_trailer_t):
  347 + tswap32s(&trailer->msgh_sender.val[0]);
  348 + tswap32s(&trailer->msgh_sender.val[1]);
  349 + /* Fall in mach_msg_seqno_trailer_t case */
  350 + case sizeof(mach_msg_seqno_trailer_t):
  351 + tswap32s(&trailer->msgh_seqno);
  352 + /* Fall in mach_msg_trailer_t case */
  353 + case sizeof(mach_msg_trailer_t):
  354 + tswap32s(&trailer->msgh_trailer_type);
  355 + tswap32s(&trailer->msgh_trailer_size);
  356 + break;
  357 + case 0:
  358 + /* Safer not to byteswap, but probably wrong */
  359 + break;
  360 + default:
  361 + qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
  362 + break;
  363 + }
  364 + }
  365 +
  366 + /* Special message handling */
  367 + switch (msg_id) {
  368 + case 200: /* host_info */
  369 + {
  370 + mig_reply_error_t *err = (mig_reply_error_t *)hdr;
  371 + struct {
  372 + uint32_t unknow1;
  373 + uint32_t maxcpu;
  374 + uint32_t numcpu;
  375 + uint32_t memsize;
  376 + uint32_t cpu_type;
  377 + uint32_t cpu_subtype;
  378 + } *data = (void *)(err+1);
  379 +
  380 + DPRINTF("maxcpu = 0x%x\n", data->maxcpu);
  381 + DPRINTF("numcpu = 0x%x\n", data->maxcpu);
  382 + DPRINTF("memsize = 0x%x\n", data->memsize);
  383 +
  384 +#if defined(TARGET_I386)
  385 + data->cpu_type = CPU_TYPE_I386;
  386 + DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
  387 +#elif defined(TARGET_PPC)
  388 + data->cpu_type = CPU_TYPE_POWERPC;
  389 + DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
  390 +#else
  391 +# error target not supported
  392 +#endif
  393 +
  394 +#if defined(TARGET_I386)
  395 + data->cpu_subtype = CPU_SUBTYPE_PENT;
  396 + DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
  397 +#elif defined(TARGET_PPC)
  398 + data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
  399 + DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
  400 +#else
  401 +# error target not supported
  402 +#endif
  403 + break;
  404 + }
  405 + case 202: /* host_page_size */
  406 + {
  407 + mig_reply_error_t *err = (mig_reply_error_t *)hdr;
  408 + uint32_t *pagesize = (uint32_t *)(err+1);
  409 +
  410 + DPRINTF("pagesize = %d\n", *pagesize);
  411 + break;
  412 + }
  413 + default: break;
  414 + }
  415 +
  416 + swap_mach_msg_header(hdr);
  417 +
  418 + return ret;
  419 +}
  420 +
  421 +long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  422 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  423 + uint32_t arg8)
  424 +{
  425 + extern uint32_t mach_reply_port();
  426 +
  427 + long ret = 0;
  428 +
  429 + arg1 = tswap32(arg1);
  430 + arg2 = tswap32(arg2);
  431 + arg3 = tswap32(arg3);
  432 + arg4 = tswap32(arg4);
  433 + arg5 = tswap32(arg5);
  434 + arg6 = tswap32(arg6);
  435 + arg7 = tswap32(arg7);
  436 + arg8 = tswap32(arg8);
  437 +
  438 + DPRINTF("mach syscall %d : " , num);
  439 +
  440 + switch(num) {
  441 + /* see xnu/osfmk/mach/syscall_sw.h */
  442 + case -26:
  443 + DPRINTF("mach_reply_port()\n");
  444 + ret = mach_reply_port();
  445 + break;
  446 + case -27:
  447 + DPRINTF("mach_thread_self()\n");
  448 + ret = mach_thread_self();
  449 + break;
  450 + case -28:
  451 + DPRINTF("mach_task_self()\n");
  452 + ret = mach_task_self();
  453 + break;
  454 + case -29:
  455 + DPRINTF("mach_host_self()\n");
  456 + ret = mach_host_self();
  457 + break;
  458 + case -31:
  459 + DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  460 + arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  461 +
  462 + ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  463 +
  464 + break;
  465 + case -36:
  466 + DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
  467 + extern int semaphore_wait_trap(int); // XXX: is there any header for that?
  468 + ret = semaphore_wait_trap(arg1);
  469 + break;
  470 + case -43:
  471 + DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  472 + arg1, arg2, arg3, arg4, arg5);
  473 + ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
  474 + tswap32s((uint32_t*)arg3);
  475 + break;
  476 + case -89:
  477 + DPRINTF("mach_timebase_info(0x%x)\n", arg1);
  478 + struct mach_timebase_info info;
  479 + ret = mach_timebase_info(&info);
  480 + if(!is_error(ret))
  481 + {
  482 + struct mach_timebase_info *outInfo = (void*)arg1;
  483 + outInfo->numer = tswap32(info.numer);
  484 + outInfo->denom = tswap32(info.denom);
  485 + }
  486 + break;
  487 + case -90:
  488 + DPRINTF("mach_wait_until()\n");
  489 + extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
  490 + ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
  491 + break;
  492 + case -91:
  493 + DPRINTF("mk_timer_create()\n");
  494 + extern int mk_timer_create(); // XXX: is there any header for that?
  495 + ret = mk_timer_create();
  496 + break;
  497 + case -92:
  498 + DPRINTF("mk_timer_destroy()\n");
  499 + extern int mk_timer_destroy(int); // XXX: is there any header for that?
  500 + ret = mk_timer_destroy(arg1);
  501 + break;
  502 + case -93:
  503 + DPRINTF("mk_timer_create()\n");
  504 + extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
  505 + ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
  506 + break;
  507 + case -94:
  508 + DPRINTF("mk_timer_cancel()\n");
  509 + extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
  510 + ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
  511 + if((!is_error(ret)) && arg2)
  512 + tswap64s((uint64_t *)arg2);
  513 + break;
  514 + default:
  515 + gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
  516 + gdb_handlesig (cpu_env, SIGTRAP);
  517 + exit(0);
  518 + break;
  519 + }
  520 + return ret;
  521 +}
  522 +
  523 +/* ------------------------------------------------------------
  524 + thread type syscall handling
  525 +*/
  526 +long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  527 + uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  528 + uint32_t arg8)
  529 +{
  530 + extern uint32_t cthread_set_self(uint32_t);
  531 + extern uint32_t processor_facilities_used();
  532 + long ret = 0;
  533 +
  534 + arg1 = tswap32(arg1);
  535 + arg2 = tswap32(arg2);
  536 + arg3 = tswap32(arg3);
  537 + arg4 = tswap32(arg4);
  538 + arg5 = tswap32(arg5);
  539 + arg6 = tswap32(arg6);
  540 + arg7 = tswap32(arg7);
  541 + arg8 = tswap32(arg8);
  542 +
  543 + DPRINTF("thread syscall %d : " , num);
  544 +
  545 + switch(num) {
  546 +#ifdef TARGET_I386
  547 + case 0x3:
  548 +#endif
  549 + case 0x7FF1: /* cthread_set_self */
  550 + DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
  551 + ret = cthread_set_self(arg1);
  552 +#ifdef TARGET_I386
  553 + /* we need to update the LDT with the address of the thread */
  554 + write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
  555 + DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  556 + (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
  557 + /* New i386 convention, %gs should be set to our this LDT entry */
  558 + cpu_x86_load_seg(cpu_env, R_GS, 0x27);
  559 + /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
  560 + ret = 0x27;
  561 +#endif
  562 + break;
  563 + case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
  564 + DPRINTF("pthread_self()\n");
  565 + ret = (uint32_t)pthread_self();
  566 + break;
  567 + case 0x7FF3:
  568 + DPRINTF("processor_facilities_used()\n");
  569 +#ifdef __i386__
  570 + qerror("processor_facilities_used: not implemented!\n");
  571 +#else
  572 + ret = (uint32_t)processor_facilities_used();
  573 +#endif
  574 + break;
  575 + default:
  576 + gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
  577 + gdb_handlesig (cpu_env, SIGTRAP);
  578 + exit(0);
  579 + break;
  580 + }
  581 + return ret;
  582 +}
  583 +
  584 +/* ------------------------------------------------------------
  585 + ioctl handling
  586 +*/
  587 +static inline void byteswap_termios(struct termios *t)
  588 +{
  589 + tswap32s((uint32_t*)&t->c_iflag);
  590 + tswap32s((uint32_t*)&t->c_oflag);
  591 + tswap32s((uint32_t*)&t->c_cflag);
  592 + tswap32s((uint32_t*)&t->c_lflag);
  593 + /* 20 (char) bytes then */
  594 + tswap32s((uint32_t*)&t->c_ispeed);
  595 + tswap32s((uint32_t*)&t->c_ospeed);
  596 +}
  597 +
  598 +static inline void byteswap_winsize(struct winsize *w)
  599 +{
  600 + tswap16s(&w->ws_row);
  601 + tswap16s(&w->ws_col);
  602 + tswap16s(&w->ws_xpixel);
  603 + tswap16s(&w->ws_ypixel);
  604 +}
  605 +
  606 +#define STRUCT(name, list...) STRUCT_ ## name,
  607 +#define STRUCT_SPECIAL(name) STRUCT_ ## name,
  608 +enum {
  609 +#include "ioctls_types.h"
  610 +};
  611 +#undef STRUCT
  612 +#undef STRUCT_SPECIAL
  613 +
  614 +#define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
  615 +#define STRUCT_SPECIAL(name)
  616 +#include "ioctls_types.h"
  617 +#undef STRUCT
  618 +#undef STRUCT_SPECIAL
  619 +
  620 +typedef struct IOCTLEntry {
  621 + unsigned int target_cmd;
  622 + unsigned int host_cmd;
  623 + const char *name;
  624 + int access;
  625 + const argtype arg_type[5];
  626 +} IOCTLEntry;
  627 +
  628 +#define IOC_R 0x0001
  629 +#define IOC_W 0x0002
  630 +#define IOC_RW (IOC_R | IOC_W)
  631 +
  632 +#define MAX_STRUCT_SIZE 4096
  633 +
  634 +IOCTLEntry ioctl_entries[] = {
  635 +#define IOCTL(cmd, access, types...) \
  636 + { cmd, cmd, #cmd, access, { types } },
  637 +#include "ioctls.h"
  638 + { 0, 0, },
  639 +};
  640 +
  641 +/* ??? Implement proper locking for ioctls. */
  642 +static long do_ioctl(long fd, long cmd, long arg)
  643 +{
  644 + const IOCTLEntry *ie;
  645 + const argtype *arg_type;
  646 + int ret;
  647 + uint8_t buf_temp[MAX_STRUCT_SIZE];
  648 + int target_size;
  649 + void *argptr;
  650 +
  651 + ie = ioctl_entries;
  652 + for(;;) {
  653 + if (ie->target_cmd == 0) {
  654 + gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
  655 + return -ENOSYS;
  656 + }
  657 + if (ie->target_cmd == cmd)
  658 + break;
  659 + ie++;
  660 + }
  661 + arg_type = ie->arg_type;
  662 +#if defined(DEBUG)
  663 + gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
  664 +#endif
  665 + switch(arg_type[0]) {
  666 + case TYPE_NULL:
  667 + /* no argument */
  668 + ret = get_errno(ioctl(fd, ie->host_cmd));
  669 + break;
  670 + case TYPE_PTRVOID:
  671 + case TYPE_INT:
  672 + /* int argment */
  673 + ret = get_errno(ioctl(fd, ie->host_cmd, arg));
  674 + break;
  675 + case TYPE_PTR:
  676 + arg_type++;
  677 + target_size = thunk_type_size(arg_type, 0);
  678 + switch(ie->access) {
  679 + case IOC_R:
  680 + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  681 + if (!is_error(ret)) {
  682 + argptr = lock_user(arg, target_size, 0);
  683 + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
  684 + unlock_user(argptr, arg, target_size);
  685 + }
  686 + break;
  687 + case IOC_W:
  688 + argptr = lock_user(arg, target_size, 1);
  689 + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
  690 + unlock_user(argptr, arg, 0);
  691 + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  692 + break;
  693 + default:
  694 + case IOC_RW:
  695 + argptr = lock_user(arg, target_size, 1);
  696 + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
  697 + unlock_user(argptr, arg, 0);
  698 + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  699 + if (!is_error(ret)) {
  700 + argptr = lock_user(arg, target_size, 0);
  701 + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
  702 + unlock_user(argptr, arg, target_size);
  703 + }
  704 + break;
  705 + }
  706 + break;
  707 + default:
  708 + gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
  709 + ret = -ENOSYS;
  710 + break;
  711 + }
  712 + return ret;
  713 +}
  714 +
  715 +/* ------------------------------------------------------------
  716 + Unix syscall handling
  717 +*/
  718 +
  719 +static inline void byteswap_attrlist(struct attrlist *a)
  720 +{
  721 + tswap16s(&a->bitmapcount);
  722 + tswap16s(&a->reserved);
  723 + tswap32s(&a->commonattr);
  724 + tswap32s(&a->volattr);
  725 + tswap32s(&a->dirattr);
  726 + tswap32s(&a->fileattr);
  727 + tswap32s(&a->forkattr);
  728 +}
  729 +
  730 +struct attrbuf_header {
  731 + unsigned long length;
  732 +};
  733 +
  734 +static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
  735 +{
  736 + DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
  737 +}
  738 +
  739 +static inline void byteswap_statfs(struct statfs *s)
  740 +{
  741 + tswap16s((uint16_t*)&s->f_otype);
  742 + tswap16s((uint16_t*)&s->f_oflags);
  743 + tswap32s((uint32_t*)&s->f_bsize);
  744 + tswap32s((uint32_t*)&s->f_iosize);
  745 + tswap32s((uint32_t*)&s->f_blocks);
  746 + tswap32s((uint32_t*)&s->f_bfree);
  747 + tswap32s((uint32_t*)&s->f_bavail);
  748 + tswap32s((uint32_t*)&s->f_files);
  749 + tswap32s((uint32_t*)&s->f_ffree);
  750 + tswap32s((uint32_t*)&s->f_fsid.val[0]);
  751 + tswap32s((uint32_t*)&s->f_fsid.val[1]);
  752 + tswap16s((uint16_t*)&s->f_reserved1);
  753 + tswap16s((uint16_t*)&s->f_type);
  754 + tswap32s((uint32_t*)&s->f_flags);
  755 +}
  756 +
  757 +static inline void byteswap_stat(struct stat *s)
  758 +{
  759 + tswap32s((uint32_t*)&s->st_dev);
  760 + tswap32s(&s->st_ino);
  761 + tswap16s(&s->st_mode);
  762 + tswap16s(&s->st_nlink);
  763 + tswap32s(&s->st_uid);
  764 + tswap32s(&s->st_gid);
  765 + tswap32s((uint32_t*)&s->st_rdev);
  766 + tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
  767 + tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
  768 + tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
  769 + tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
  770 + tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
  771 + tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
  772 + tswap64s((uint64_t*)&s->st_size);
  773 + tswap64s((uint64_t*)&s->st_blocks);
  774 + tswap32s((uint32_t*)&s->st_blksize);
  775 + tswap32s(&s->st_flags);
  776 + tswap32s(&s->st_gen);
  777 +}
  778 +
  779 +static inline void byteswap_dirents(struct dirent *d, int bytes)
  780 +{
  781 + char *b;
  782 + for( b = (char*)d; (int)b < (int)d+bytes; )
  783 + {
  784 + unsigned short s = ((struct dirent *)b)->d_reclen;
  785 + tswap32s(&((struct dirent *)b)->d_ino);
  786 + tswap16s(&((struct dirent *)b)->d_reclen);
  787 + if(s<=0)
  788 + break;
  789 + b += s;
  790 + }
  791 +}
  792 +
  793 +static inline void byteswap_iovec(struct iovec *v, int n)
  794 +{
  795 + int i;
  796 + for(i = 0; i < n; i++)
  797 + {
  798 + tswap32s((uint32_t*)&v[i].iov_base);
  799 + tswap32s((uint32_t*)&v[i].iov_len);
  800 + }
  801 +}
  802 +
  803 +static inline void byteswap_timeval(struct timeval *t)
  804 +{
  805 + tswap32s((uint32_t*)&t->tv_sec);
  806 + tswap32s((uint32_t*)&t->tv_usec);
  807 +}
  808 +
  809 +long do_unix_syscall_indirect(void *cpu_env, int num);
  810 +long do_sync();
  811 +long do_exit(uint32_t arg1);
  812 +long do_getlogin(char *out, uint32_t size);
  813 +long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
  814 +long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
  815 +long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
  816 +long do_execve(char* arg1, char ** arg2, char ** arg3);
  817 +long do_getgroups(uint32_t arg1, gid_t * arg2);
  818 +long do_gettimeofday(struct timeval * arg1, void * arg2);
  819 +long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
  820 +long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
  821 +long do_utimes(char * arg1, struct timeval * arg2);
  822 +long do_futimes(uint32_t arg1, struct timeval * arg2);
  823 +long do_statfs(char * arg1, struct statfs * arg2);
  824 +long do_fstatfs(uint32_t arg1, struct statfs * arg2);
  825 +long do_stat(char * arg1, struct stat * arg2);
  826 +long do_fstat(uint32_t arg1, struct stat * arg2);
  827 +long do_lstat(char * arg1, struct stat * arg2);
  828 +long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
  829 +long do_lseek(void *cpu_env, int num);
  830 +long do___sysctl(void * arg1, uint32_t arg2, void * arg3, void * arg4, void * arg5, size_t arg6);
  831 +long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
  832 +long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
  833 +
  834 +long no_syscall(void *cpu_env, int num);
  835 +
  836 +long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
  837 +{
  838 + //DPRINTF("0x%x, 0x%x, 0x%x, 0x%llx\n", arg1, arg2, arg3, arg4);
  839 + long ret = (pread(arg1, arg2, arg3, arg4));
  840 + DPRINTF("0x%x\n", *(int*)arg2);
  841 + return ret;
  842 +}
  843 +long unimpl_unix_syscall(void *cpu_env, int num);
  844 +
  845 +typedef long (*syscall_function_t)(void *cpu_env, int num);
  846 +
  847 +
  848 +/* define a table that will handle the syscall number->function association */
  849 +#define VOID void
  850 +#define INT (uint32_t)get_int_arg(&i, cpu_env)
  851 +#define INT64 (uint64_t)get_int64_arg(&i, cpu_env)
  852 +#define UINT (unsigned int)INT
  853 +#define PTR (void*)INT
  854 +
  855 +#define SIZE INT
  856 +#define OFFSET INT64
  857 +
  858 +#define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) { return (long)function(); }
  859 +#define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1; return (long)function(arg1); }
  860 +#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); }
  861 +#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); }
  862 +#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); }
  863 +#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); }
  864 +#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); }
  865 +#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); }
  866 +#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); }
  867 +#define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
  868 +#define WRAPPER_CALL_NOERRNO(function, nargs, args...) WRAPPER_CALL_DIRECT(function, nargs, args)
  869 +#define WRAPPER_CALL_INDIRECT(function, nargs, args...)
  870 +#define ENTRY(name, number, function, nargs, call_type, args...) WRAPPER_##call_type(function, nargs, args)
  871 +
  872 +#include "syscalls.h"
  873 +
  874 +#undef ENTRY
  875 +#undef WRAPPER_CALL_DIRECT
  876 +#undef WRAPPER_CALL_NOERRNO
  877 +#undef WRAPPER_CALL_INDIRECT
  878 +#undef OFFSET
  879 +#undef SIZE
  880 +#undef INT
  881 +#undef PTR
  882 +#undef INT64
  883 +
  884 +#define _ENTRY(name, number, function, nargs, call_type) [number] = {\
  885 + name, \
  886 + number, \
  887 + (syscall_function_t)function, \
  888 + nargs, \
  889 + call_type \
  890 + },
  891 +
  892 +#define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, __qemu_##function, nargs, call_type)
  893 +#define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
  894 +#define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
  895 +#define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
  896 +
  897 +#define CALL_DIRECT 1
  898 +#define CALL_INDIRECT 2
  899 +#define CALL_NOERRNO (CALL_DIRECT | 4 /* = 5 */)
  900 +
  901 +struct unix_syscall {
  902 + char * name;
  903 + int number;
  904 + syscall_function_t function;
  905 + int nargs;
  906 + int call_type;
  907 +} unix_syscall_table[SYS_MAXSYSCALL] = {
  908 +#include "syscalls.h"
  909 +};
  910 +
  911 +#undef ENTRY
  912 +#undef _ENTRY
  913 +#undef ENTRY_CALL_DIRECT
  914 +#undef ENTRY_CALL_INDIRECT
  915 +#undef ENTRY_CALL_NOERRNO
  916 +
  917 +/* Actual syscalls implementation */
  918 +
  919 +long do_unix_syscall_indirect(void *cpu_env, int num)
  920 +{
  921 + long ret;
  922 + int new_num;
  923 + int i = 0;
  924 +
  925 + new_num = get_int_arg(&i, cpu_env);
  926 +#ifdef TARGET_I386
  927 + ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
  928 + /* XXX: not necessary */
  929 + ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
  930 +#elif TARGET_PPC
  931 + {
  932 + int i;
  933 + uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
  934 + for(i = 3; i < 11; i++)
  935 + *regs[i] = *regs[i+1];
  936 + /* XXX: not necessary */
  937 + *regs[0] = new_num;
  938 + }
  939 +#endif
  940 + ret = do_unix_syscall(cpu_env, new_num);
  941 +#ifdef TARGET_I386
  942 + ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
  943 + /* XXX: not necessary */
  944 + ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
  945 +#elif TARGET_PPC
  946 + {
  947 + int i;
  948 + /* XXX: not really needed those regs are volatile accross calls */
  949 + uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
  950 + for(i = 11; i > 3; i--)
  951 + *regs[i] = *regs[i-1];
  952 + regs[3] = new_num;
  953 + *regs[0] = num;
  954 + }
  955 +#endif
  956 + return ret;
  957 +}
  958 +
  959 +long do_exit(uint32_t arg1)
  960 +{
  961 + exit(arg1);
  962 + /* not reached */
  963 + return -1;
  964 +}
  965 +
  966 +long do_sync()
  967 +{
  968 + sync();
  969 + return 0;
  970 +}
  971 +
  972 +long do_getlogin(char *out, uint32_t size)
  973 +{
  974 + char *login = getlogin();
  975 + if(!login)
  976 + return -1;
  977 + memcpy(out, login, size);
  978 + return 0;
  979 +}
  980 +long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
  981 +{
  982 + /* XXX: don't let the %s stay in there */
  983 + DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
  984 + return get_errno(open(arg1, arg2, arg3));
  985 +}
  986 +
  987 +long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
  988 +{
  989 + long ret;
  990 + DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
  991 + ret = get_errno(getfsstat(arg1, arg2, arg3));
  992 + if((!is_error(ret)) && arg1)
  993 + byteswap_statfs(arg1);
  994 + return ret;
  995 +}
  996 +
  997 +long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
  998 +{
  999 + long ret;
  1000 + DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
  1001 + gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
  1002 + if(arg2)
  1003 + tswap32s(arg2);
  1004 + ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
  1005 + if((!is_error(ret)) && arg3)
  1006 + tswap32s(arg3);
  1007 + if(arg2)
  1008 + tswap32s(arg2);
  1009 + return ret;
  1010 +}
  1011 +
  1012 +long do_execve(char* arg1, char ** arg2, char ** arg3)
  1013 +{
  1014 + long ret;
  1015 + char **argv = arg2;
  1016 + char **envp = arg3;
  1017 + int argc;
  1018 + int envc;
  1019 +
  1020 + /* XXX: don't let the %s stay in here */
  1021 + DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
  1022 +
  1023 + for(argc = 0; argv[argc]; argc++);
  1024 + for(envc = 0; envp[envc]; envc++);
  1025 +
  1026 + argv = (char**)malloc(sizeof(char*)*argc);
  1027 + envp = (char**)malloc(sizeof(char*)*envc);
  1028 +
  1029 + for(; argc >= 0; argc--)
  1030 + argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
  1031 +
  1032 + for(; envc >= 0; envc--)
  1033 + envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
  1034 +
  1035 + ret = get_errno(execve(arg1, argv, envp));
  1036 + free(argv);
  1037 + free(envp);
  1038 + return ret;
  1039 +}
  1040 +
  1041 +long do_getgroups(uint32_t arg1, gid_t * arg2)
  1042 +{
  1043 + long ret;
  1044 + int i;
  1045 + DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
  1046 + ret = get_errno(getgroups(arg1, arg2));
  1047 + if(ret > 0)
  1048 + for(i = 0; i < arg1; i++)
  1049 + tswap32s(&arg2[i]);
  1050 + return ret;
  1051 +}
  1052 +
  1053 +long do_gettimeofday(struct timeval * arg1, void * arg2)
  1054 +{
  1055 + long ret;
  1056 + DPRINTF("gettimeofday(%p, %p)\n",
  1057 + arg1, arg2);
  1058 + ret = get_errno(gettimeofday(arg1, arg2));
  1059 + if(!is_error(ret))
  1060 + {
  1061 + /* timezone no longer used according to the manpage, so don't bother with it */
  1062 + byteswap_timeval(arg1);
  1063 + }
  1064 + return ret;
  1065 +}
  1066 +
  1067 +long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
  1068 +{
  1069 + long ret;
  1070 + DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
  1071 + if(arg2)
  1072 + byteswap_iovec(arg2, arg3);
  1073 + ret = get_errno(readv(arg1, arg2, arg3));
  1074 + if((!is_error(ret)) && arg2)
  1075 + byteswap_iovec(arg2, arg3);
  1076 + return ret;
  1077 +}
  1078 +
  1079 +long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
  1080 +{
  1081 + long ret;
  1082 + DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
  1083 + if(arg2)
  1084 + byteswap_iovec(arg2, arg3);
  1085 + ret = get_errno(writev(arg1, arg2, arg3));
  1086 + if((!is_error(ret)) && arg2)
  1087 + byteswap_iovec(arg2, arg3);
  1088 + return ret;
  1089 +}
  1090 +
  1091 +long do_utimes(char * arg1, struct timeval * arg2)
  1092 +{
  1093 + DPRINTF("utimes(%p, %p)\n", arg1, arg2);
  1094 + if(arg2)
  1095 + {
  1096 + byteswap_timeval(arg2);
  1097 + byteswap_timeval(arg2+1);
  1098 + }
  1099 + return get_errno(utimes(arg1, arg2));
  1100 +}
  1101 +
  1102 +long do_futimes(uint32_t arg1, struct timeval * arg2)
  1103 +{
  1104 + DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
  1105 + if(arg2)
  1106 + {
  1107 + byteswap_timeval(arg2);
  1108 + byteswap_timeval(arg2+1);
  1109 + }
  1110 + return get_errno(futimes(arg1, arg2));
  1111 +}
  1112 +
  1113 +long do_statfs(char * arg1, struct statfs * arg2)
  1114 +{
  1115 + long ret;
  1116 + DPRINTF("statfs(%p, %p)\n", arg1, arg2);
  1117 + ret = get_errno(statfs(arg1, arg2));
  1118 + if(!is_error(ret))
  1119 + byteswap_statfs(arg2);
  1120 + return ret;
  1121 +}
  1122 +
  1123 +long do_fstatfs(uint32_t arg1, struct statfs* arg2)
  1124 +{
  1125 + long ret;
  1126 + DPRINTF("fstatfs(0x%x, %p)\n",
  1127 + arg1, arg2);
  1128 + ret = get_errno(fstatfs(arg1, arg2));
  1129 + if(!is_error(ret))
  1130 + byteswap_statfs(arg2);
  1131 +
  1132 + return ret;
  1133 +}
  1134 +
  1135 +long do_stat(char * arg1, struct stat * arg2)
  1136 +{
  1137 + long ret;
  1138 + /* XXX: don't let the %s stay in there */
  1139 + DPRINTF("stat(%s, %p)\n", arg1, arg2);
  1140 + ret = get_errno(stat(arg1, arg2));
  1141 + if(!is_error(ret))
  1142 + byteswap_stat(arg2);
  1143 + return ret;
  1144 +}
  1145 +
  1146 +long do_fstat(uint32_t arg1, struct stat * arg2)
  1147 +{
  1148 + long ret;
  1149 + DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
  1150 + ret = get_errno(fstat(arg1, arg2));
  1151 + if(!is_error(ret))
  1152 + byteswap_stat(arg2);
  1153 + return ret;
  1154 +}
  1155 +
  1156 +long do_lstat(char * arg1, struct stat * arg2)
  1157 +{
  1158 + long ret;
  1159 + /* XXX: don't let the %s stay in there */
  1160 + DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
  1161 + ret = get_errno(lstat(arg1, arg2));
  1162 + if(!is_error(ret))
  1163 + byteswap_stat(arg2);
  1164 + return ret;
  1165 +}
  1166 +
  1167 +long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
  1168 +{
  1169 + long ret;
  1170 + DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
  1171 + if(arg4)
  1172 + tswap32s((uint32_t *)arg4);
  1173 + ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
  1174 + if(arg4)
  1175 + tswap32s((uint32_t *)arg4);
  1176 + if(!is_error(ret))
  1177 + byteswap_dirents(arg2, ret);
  1178 + return ret;
  1179 +}
  1180 +
  1181 +long do_lseek(void *cpu_env, int num)
  1182 +{
  1183 + long ret;
  1184 + int i = 0;
  1185 + uint32_t arg1 = get_int_arg(&i, cpu_env);
  1186 + uint64_t offset = get_int64_arg(&i, cpu_env);
  1187 + uint32_t arg3 = get_int_arg(&i, cpu_env);
  1188 + uint64_t r = lseek(arg1, offset, arg3);
  1189 +#ifdef TARGET_I386
  1190 + /* lowest word in eax, highest in edx */
  1191 + ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
  1192 + ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
  1193 +#elif defined TARGET_PPC
  1194 + ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
  1195 + ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
  1196 +#else
  1197 + qerror("64 bit ret value on your arch?");
  1198 +#endif
  1199 + return get_errno(ret);
  1200 +}
  1201 +
  1202 +long do___sysctl(void * arg1, uint32_t arg2, void * arg3, void * arg4, void * arg5, size_t arg6)
  1203 +{
  1204 + long ret = 0;
  1205 + int i;
  1206 + DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
  1207 + arg1, arg2, arg3, arg4, arg5, arg6);
  1208 + if(arg1) {
  1209 + i = 0;
  1210 + do { *((int *) arg1 + i) = tswap32(*((int *) arg1 + i)); } while (++i < arg2);
  1211 + }
  1212 +
  1213 + if(arg4)
  1214 + *(int *) arg4 = tswap32(*(int *) arg4);
  1215 + if(arg1)
  1216 + ret = get_errno(sysctl((void *)arg1, arg2, (void *)arg3, (void *)arg4, (void *)arg5, arg6));
  1217 +
  1218 + if ((ret == 0) && (arg2 == 2) && (*((int *) arg1) == 0) && (*((int *) arg1 + 1) == 3)) {
  1219 + /* The output here is the new id - we need to swap it so it can be passed
  1220 + back in (and then unswapped) */
  1221 + int count = (*(int *) arg4) / sizeof(int);
  1222 + i = 0;
  1223 + do {
  1224 + *((int *) arg3 + i) = tswap32(*((int *) arg3 + i));
  1225 + } while (++i < count);
  1226 + }
  1227 + *(int *) arg4 = tswap32(*(int *) arg4);
  1228 +
  1229 + return ret;
  1230 +}
  1231 +
  1232 +long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
  1233 +{
  1234 + struct attrlist * attrlist = (void *)arg2;
  1235 + long ret;
  1236 +
  1237 +#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
  1238 + qerror("SYS_getdirentriesattr unimplemented\n");
  1239 +#endif
  1240 + /* XXX: don't let the %s stay in there */
  1241 + DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
  1242 + (char *)arg1, arg2, arg3, arg4, arg5);
  1243 +
  1244 + if(arg2) /* XXX: We should handle that in a copy especially
  1245 + if the structure is not writable */
  1246 + byteswap_attrlist(attrlist);
  1247 +
  1248 + ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
  1249 +
  1250 + if(!is_error(ret))
  1251 + {
  1252 + byteswap_attrbuf((void *)arg3, attrlist);
  1253 + byteswap_attrlist(attrlist);
  1254 + }
  1255 + return ret;
  1256 +}
  1257 +
  1258 +long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
  1259 +{
  1260 + DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
  1261 + arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
  1262 +#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
  1263 + qerror("SYS_getdirentriesattr unimplemented\n");
  1264 +#endif
  1265 +
  1266 + return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
  1267 + (unsigned long *)arg5, (unsigned long *)arg6,
  1268 + (unsigned long *)arg7, arg8));
  1269 +}
  1270 +
  1271 +
  1272 +long no_syscall(void *cpu_env, int num)
  1273 +{
  1274 + /* XXX: We should probably fordward it to the host kernel */
  1275 + qerror("no unix syscall %d\n", num);
  1276 + /* not reached */
  1277 + return -1;
  1278 +}
  1279 +
  1280 +long unimpl_unix_syscall(void *cpu_env, int num)
  1281 +{
  1282 + if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
  1283 + qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
  1284 +
  1285 + gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
  1286 + gdb_handlesig (cpu_env, SIGTRAP);
  1287 + exit(-1);
  1288 +}
  1289 +
  1290 +long do_unix_syscall(void *cpu_env, int num)
  1291 +{
  1292 + long ret = 0;
  1293 +
  1294 + DPRINTF("unix syscall %d: " , num);
  1295 +
  1296 + if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
  1297 + qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
  1298 +
  1299 + DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
  1300 + ret = unix_syscall_table[num].function(cpu_env, num);
  1301 +
  1302 + if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
  1303 + ret = get_errno(ret);
  1304 +
  1305 + DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
  1306 + return ret;
  1307 +}
  1308 +
  1309 +/* ------------------------------------------------------------
  1310 + syscall_init
  1311 +*/
  1312 +void syscall_init(void)
  1313 +{
  1314 + /* Nothing yet */
  1315 +}
... ...