Drop darwin-user

It's been orphaned, not compiling for a long time and despite Apple's
drop of their Rosetta ppc emulation technology with Mac OS X Lion no one
has stepped up to fix it.

Testing necessary changes wrt QOM'ification thus is impossible, so we
might as well remove it completely.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Andreas Färber 2012-04-16 04:31:11 +00:00 committed by Andreas Färber
parent 148210301e
commit 0adb124659
17 changed files with 1 additions and 5434 deletions

View file

@ -570,11 +570,6 @@ M: Blue Swirl <blauwirbel@gmail.com>
S: Maintained S: Maintained
F: bsd-user/ F: bsd-user/
Darwin user
M: qemu-devel@nongnu.org
S: Orphan
F: darwin-user/
Linux user Linux user
M: Riku Voipio <riku.voipio@iki.fi> M: Riku Voipio <riku.voipio@iki.fi>
S: Maintained S: Maintained

View file

@ -161,34 +161,6 @@ obj-y += $(libobj-y)
endif #CONFIG_LINUX_USER endif #CONFIG_LINUX_USER
#########################################################
# Darwin user emulator target
ifdef CONFIG_DARWIN_USER
$(call set-vpath, $(SRC_PATH)/darwin-user)
QEMU_CFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
# Leave some space for the regular program loading zone
LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
LIBS+=-lmx
obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
gdbstub.o user-exec.o
obj-i386-y += ioport-user.o
$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y): $(GENERATED_HEADERS)
obj-y += $(addprefix ../, $(universal-obj-y))
obj-y += $(addprefix ../libuser/, $(user-obj-y))
obj-y += $(addprefix ../libdis-user/, $(libdis-y))
obj-y += $(libobj-y)
endif #CONFIG_DARWIN_USER
######################################################### #########################################################
# BSD user emulator target # BSD user emulator target

25
configure vendored
View file

@ -173,7 +173,6 @@ profiler="no"
cocoa="no" cocoa="no"
softmmu="yes" softmmu="yes"
linux_user="no" linux_user="no"
darwin_user="no"
bsd_user="no" bsd_user="no"
guest_base="" guest_base=""
uname_release="" uname_release=""
@ -424,7 +423,6 @@ Darwin)
else else
QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS" QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS"
fi fi
darwin_user="yes"
cocoa="yes" cocoa="yes"
audio_drv_list="coreaudio" audio_drv_list="coreaudio"
audio_possible_drivers="coreaudio sdl fmod" audio_possible_drivers="coreaudio sdl fmod"
@ -728,17 +726,12 @@ for opt do
--disable-user) --disable-user)
linux_user="no" ; linux_user="no" ;
bsd_user="no" ; bsd_user="no" ;
darwin_user="no"
;; ;;
--enable-user) ;; --enable-user) ;;
--disable-linux-user) linux_user="no" --disable-linux-user) linux_user="no"
;; ;;
--enable-linux-user) linux_user="yes" --enable-linux-user) linux_user="yes"
;; ;;
--disable-darwin-user) darwin_user="no"
;;
--enable-darwin-user) darwin_user="yes"
;;
--disable-bsd-user) bsd_user="no" --disable-bsd-user) bsd_user="no"
;; ;;
--enable-bsd-user) bsd_user="yes" --enable-bsd-user) bsd_user="yes"
@ -967,10 +960,6 @@ unicore32-linux-user \
s390x-linux-user \ s390x-linux-user \
" "
fi fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
default_target_list="$default_target_list i386-darwin-user ppc-darwin-user "
fi
# the following are BSD specific # the following are BSD specific
if [ "$bsd_user" = "yes" ] ; then if [ "$bsd_user" = "yes" ] ; then
default_target_list="${default_target_list}\ default_target_list="${default_target_list}\
@ -1072,8 +1061,6 @@ echo " --enable-user enable supported user emulation targets"
echo " --disable-user disable all user emulation targets" echo " --disable-user disable all user emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets" echo " --enable-linux-user enable all linux usermode emulation targets"
echo " --disable-linux-user disable all linux usermode emulation targets" echo " --disable-linux-user disable all linux usermode emulation targets"
echo " --enable-darwin-user enable all darwin usermode emulation targets"
echo " --disable-darwin-user disable all darwin usermode emulation targets"
echo " --enable-bsd-user enable all BSD usermode emulation targets" echo " --enable-bsd-user enable all BSD usermode emulation targets"
echo " --disable-bsd-user disable all BSD usermode emulation targets" echo " --disable-bsd-user disable all BSD usermode emulation targets"
echo " --enable-guest-base enable GUEST_BASE support for usermode" echo " --enable-guest-base enable GUEST_BASE support for usermode"
@ -3472,7 +3459,6 @@ esac
target_softmmu="no" target_softmmu="no"
target_user_only="no" target_user_only="no"
target_linux_user="no" target_linux_user="no"
target_darwin_user="no"
target_bsd_user="no" target_bsd_user="no"
case "$target" in case "$target" in
${target_arch2}-softmmu) ${target_arch2}-softmmu)
@ -3486,14 +3472,6 @@ case "$target" in
target_user_only="yes" target_user_only="yes"
target_linux_user="yes" target_linux_user="yes"
;; ;;
${target_arch2}-darwin-user)
if test "$darwin" != "yes" ; then
echo "ERROR: Target '$target' is only available on a Darwin host"
exit 1
fi
target_user_only="yes"
target_darwin_user="yes"
;;
${target_arch2}-bsd-user) ${target_arch2}-bsd-user)
if test "$bsd" != "yes" ; then if test "$bsd" != "yes" ; then
echo "ERROR: Target '$target' is only available on a BSD host" echo "ERROR: Target '$target' is only available on a BSD host"
@ -3747,9 +3725,6 @@ fi
if test "$target_linux_user" = "yes" ; then if test "$target_linux_user" = "yes" ; then
echo "CONFIG_LINUX_USER=y" >> $config_target_mak echo "CONFIG_LINUX_USER=y" >> $config_target_mak
fi fi
if test "$target_darwin_user" = "yes" ; then
echo "CONFIG_DARWIN_USER=y" >> $config_target_mak
fi
list="" list=""
if test ! -z "$gdb_xml_files" ; then if test ! -z "$gdb_xml_files" ; then
for x in $gdb_xml_files; do for x in $gdb_xml_files; do

View file

@ -1,357 +0,0 @@
/*
* Commpage syscalls
*
* Copyright (c) 2006 Pierre d'Herbemont
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <mach/message.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <libkern/OSAtomic.h>
#include "qemu.h"
//#define DEBUG_COMMPAGE
#ifdef DEBUG_COMMPAGE
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
#else
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
#endif
/********************************************************************
* Commpage definitions
*/
#ifdef TARGET_I386
/* Reserve space for the commpage see xnu/osfmk/i386/cpu_capabilities.h */
# define COMMPAGE_START (-16 * 4096) /* base address is -20 * 4096 */
# define COMMPAGE_SIZE (0x1240) /* _COMM_PAGE_AREA_LENGTH is 19 * 4096 */
#elif defined(TARGET_PPC)
/* Reserve space for the commpage see xnu/osfmk/ppc/cpu_capabilities.h */
# define COMMPAGE_START (-8*4096)
# define COMMPAGE_SIZE (2*4096) /* its _COMM_PAGE_AREA_USED but _COMM_PAGE_AREA_LENGTH is 7*4096 */
#endif
void do_compare_and_swap32(void *cpu_env, int num);
void do_compare_and_swap64(void *cpu_env, int num);
void do_add_atomic_word32(void *cpu_env, int num);
void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1);
void do_nanotime(void *cpu_env, int num);
void unimpl_commpage(void *cpu_env, int num);
typedef void (*commpage_8args_function_t)(uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
uint32_t arg8);
typedef void (*commpage_indirect_function_t)(void *cpu_env, int num, uint32_t arg1,
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
uint32_t arg6, uint32_t arg7, uint32_t arg8);
#define HAS_PTR 0x10
#define NO_PTR 0x20
#define CALL_DIRECT 0x1
#define CALL_INDIRECT 0x2
#define COMMPAGE_ENTRY(name, nargs, offset, func, options) \
{ #name, offset, nargs, options, (commpage_8args_function_t)func }
struct commpage_entry {
char * name;
int offset;
int nargs;
char options;
commpage_8args_function_t function;
};
static inline int commpage_code_num(struct commpage_entry *entry)
{
if((entry->options & HAS_PTR))
return entry->offset + 4;
else
return entry->offset;
}
static inline int commpage_is_indirect(struct commpage_entry *entry)
{
return !(entry->options & CALL_DIRECT);
}
/********************************************************************
* Commpage entry
*/
static struct commpage_entry commpage_entries[] =
{
COMMPAGE_ENTRY(compare_and_swap32, 0, 0x080, do_compare_and_swap32, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(compare_and_swap64, 0, 0x0c0, do_compare_and_swap64, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(enqueue, 0, 0x100, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(dequeue, 0, 0x140, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(memory_barrier, 0, 0x180, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(add_atomic_word32, 0, 0x1a0, do_add_atomic_word32, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(add_atomic_word64, 0, 0x1c0, unimpl_commpage, CALL_INDIRECT | HAS_PTR),
COMMPAGE_ENTRY(mach_absolute_time, 0, 0x200, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(spinlock_try, 1, 0x220, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(spinlock_lock, 1, 0x260, OSSpinLockLock, CALL_DIRECT),
COMMPAGE_ENTRY(spinlock_unlock, 1, 0x2a0, OSSpinLockUnlock, CALL_DIRECT),
COMMPAGE_ENTRY(pthread_getspecific, 0, 0x2c0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(gettimeofday, 1, 0x2e0, do_cgettimeofday, CALL_INDIRECT),
COMMPAGE_ENTRY(sys_dcache_flush, 0, 0x4e0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(sys_icache_invalidate, 0, 0x520, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(pthread_self, 0, 0x580, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(relinquish, 0, 0x5c0, unimpl_commpage, CALL_INDIRECT),
#ifdef TARGET_I386
COMMPAGE_ENTRY(bts, 0, 0x5e0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(btc, 0, 0x5f0, unimpl_commpage, CALL_INDIRECT),
#endif
COMMPAGE_ENTRY(bzero, 2, 0x600, bzero, CALL_DIRECT),
COMMPAGE_ENTRY(bcopy, 3, 0x780, bcopy, CALL_DIRECT),
COMMPAGE_ENTRY(memcpy, 3, 0x7a0, memcpy, CALL_DIRECT),
#ifdef TARGET_I386
COMMPAGE_ENTRY(old_nanotime, 0, 0xf80, do_nanotime, CALL_INDIRECT),
COMMPAGE_ENTRY(memset_pattern, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(long_copy, 0, 0x1200, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(sysintegrity, 0, 0x1600, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(nanotime, 0, 0x1700, do_nanotime, CALL_INDIRECT),
#elif TARGET_PPC
COMMPAGE_ENTRY(compare_and_swap32b, 0, 0xf80, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(compare_and_swap64b, 0, 0xfc0, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(memset_pattern, 0, 0x1000, unimpl_commpage, CALL_INDIRECT),
COMMPAGE_ENTRY(bigcopy, 0, 0x1140, unimpl_commpage, CALL_INDIRECT),
#endif
};
/********************************************************************
* Commpage backdoor
*/
static inline void print_commpage_entry(struct commpage_entry entry)
{
printf("@0x%x %s\n", entry.offset, entry.name);
}
static inline void install_commpage_backdoor_for_entry(struct commpage_entry entry)
{
#ifdef TARGET_I386
char * commpage = (char*)(COMMPAGE_START+entry.offset);
int c = 0;
if(entry.options & HAS_PTR)
{
commpage[c++] = (COMMPAGE_START+entry.offset+4) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 8) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 16) & 0xff;
commpage[c++] = ((COMMPAGE_START+entry.offset+4) >> 24) & 0xff;
}
commpage[c++] = 0xcd;
commpage[c++] = 0x79; /* int 0x79 */
commpage[c++] = 0xc3; /* ret */
#else
qerror("can't install the commpage on this arch\n");
#endif
}
/********************************************************************
* Commpage initialization
*/
void commpage_init(void)
{
#if (defined(__i386__) ^ defined(TARGET_I386)) || (defined(_ARCH_PPC) ^ defined(TARGET_PPC))
int i;
void * commpage = (void *)target_mmap( COMMPAGE_START, COMMPAGE_SIZE,
PROT_WRITE | PROT_READ, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if((int)commpage != COMMPAGE_START)
qerror("can't allocate the commpage\n");
bzero(commpage, COMMPAGE_SIZE);
/* XXX: commpage data not handled */
for(i = 0; i < ARRAY_SIZE(commpage_entries); i++)
install_commpage_backdoor_for_entry(commpage_entries[i]);
#else
/* simply map our pages so they can be executed
XXX: we don't really want to do that since in the ppc on ppc situation we may
not able to run commpages host optimized instructions (like G5's on a G5),
hence this is sometimes a broken fix. */
page_set_flags(COMMPAGE_START, COMMPAGE_START+COMMPAGE_SIZE, PROT_EXEC | PROT_READ | PAGE_VALID);
#endif
}
/********************************************************************
* Commpage implementation
*/
void do_compare_and_swap32(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint32_t old = ((CPUX86State*)cpu_env)->regs[R_EAX];
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
if(old == tswap32(*value))
{
uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
*value = tswap32(new);
/* set zf flag */
((CPUX86State*)cpu_env)->eflags |= 0x40;
}
else
{
((CPUX86State*)cpu_env)->regs[R_EAX] = tswap32(*value);
/* unset zf flag */
((CPUX86State*)cpu_env)->eflags &= ~0x40;
}
#else
qerror("do_compare_and_swap32 unimplemented");
#endif
}
void do_compare_and_swap64(void *cpu_env, int num)
{
#ifdef TARGET_I386
/* OSAtomicCompareAndSwap64 is not available on non 64 bits ppc, here is a raw implementation */
uint64_t old, new, swapped_val;
uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
DPRINTF("commpage: compare_and_swap64(%" PRIx64 ",new,%p)\n", old, value);
swapped_val = tswap64(*value);
if(old == swapped_val)
{
new = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_ECX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EBX];
*value = tswap64(new);
/* set zf flag */
((CPUX86State*)cpu_env)->eflags |= 0x40;
}
else
{
((CPUX86State*)cpu_env)->regs[R_EAX] = (uint32_t)(swapped_val);
((CPUX86State*)cpu_env)->regs[R_EDX] = (uint32_t)(swapped_val >> 32);
/* unset zf flag */
((CPUX86State*)cpu_env)->eflags &= ~0x40;
}
#else
qerror("do_compare_and_swap64 unimplemented");
#endif
}
void do_add_atomic_word32(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint32_t amt = ((CPUX86State*)cpu_env)->regs[R_EAX];
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_EDX];
uint32_t swapped_value = tswap32(*value);
DPRINTF("commpage: add_atomic_word32(%x,%p)\n", amt, value);
/* old value in EAX */
((CPUX86State*)cpu_env)->regs[R_EAX] = swapped_value;
*value = tswap32(swapped_value + amt);
#else
qerror("do_add_atomic_word32 unimplemented");
#endif
}
void do_cgettimeofday(void *cpu_env, int num, uint32_t arg1)
{
#ifdef TARGET_I386
extern int __commpage_gettimeofday(struct timeval *);
DPRINTF("commpage: gettimeofday(0x%x)\n", arg1);
struct timeval *time = (struct timeval *)arg1;
int ret = __commpage_gettimeofday(time);
tswap32s((uint32_t*)&time->tv_sec);
tswap32s((uint32_t*)&time->tv_usec);
((CPUX86State*)cpu_env)->regs[R_EAX] = ret; /* Success */
#else
qerror("do_gettimeofday unimplemented");
#endif
}
void do_nanotime(void *cpu_env, int num)
{
#ifdef TARGET_I386
uint64_t t = mach_absolute_time();
((CPUX86State*)cpu_env)->regs[R_EAX] = (int)(t & 0xffffffff);
((CPUX86State*)cpu_env)->regs[R_EDX] = (int)((t >> 32) & 0xffffffff);
#else
qerror("do_nanotime unimplemented");
#endif
}
void unimpl_commpage(void *cpu_env, int num)
{
qerror("qemu: commpage function 0x%x not implemented\n", num);
}
/********************************************************************
* do_commpage - called by the main cpu loop
*/
void
do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
uint32_t arg8)
{
int i, found = 0;
arg1 = tswap32(arg1);
arg2 = tswap32(arg2);
arg3 = tswap32(arg3);
arg4 = tswap32(arg4);
arg5 = tswap32(arg5);
arg6 = tswap32(arg6);
arg7 = tswap32(arg7);
arg8 = tswap32(arg8);
num = num-COMMPAGE_START-2;
for(i = 0; i < ARRAY_SIZE(commpage_entries); i++) {
if( num == commpage_code_num(&commpage_entries[i]) )
{
DPRINTF("commpage: %s %s\n", commpage_entries[i].name, commpage_is_indirect(&commpage_entries[i]) ? "[indirect]" : "[direct]");
found = 1;
if(commpage_is_indirect(&commpage_entries[i]))
{
commpage_indirect_function_t function = (commpage_indirect_function_t)commpage_entries[i].function;
function(cpu_env, num, arg1, arg2, arg3,
arg4, arg5, arg6, arg7, arg8);
}
else
{
commpage_entries[i].function(arg1, arg2, arg3,
arg4, arg5, arg6, arg7, arg8);
}
break;
}
}
if(!found)
{
gemu_log("qemu: commpage function 0x%x not defined\n", num);
gdb_handlesig (cpu_env, SIGTRAP);
exit(-1);
}
}

View file

@ -1,4 +0,0 @@
/* emulated ioctl list */
IOCTL(TIOCGETA, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TIOCSETA, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))

View file

@ -1 +0,0 @@
STRUCT(termios, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_CHAR, 20), TYPE_INT, TYPE_INT)

View file

@ -1,902 +0,0 @@
/*
* Mach-O object file loading
*
* Copyright (c) 2006 Pierre d'Herbemont
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include "qemu.h"
#include "disas.h"
#include <mach-o/loader.h>
#include <mach-o/fat.h>
#include <mach-o/nlist.h>
#include <mach-o/reloc.h>
#include <mach-o/ppc/reloc.h>
//#define DEBUG_MACHLOAD
#ifdef DEBUG_MACHLOAD
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); printf(__VA_ARGS__); } while(0)
#else
# define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
#endif
# define check_mach_header(x) (x.magic == MH_CIGAM)
extern const char *interp_prefix;
/* we don't have a good implementation for this */
#define DONT_USE_DYLD_SHARED_MAP
/* Pass extra arg to DYLD for debug */
//#define ACTIVATE_DYLD_TRACE
//#define OVERRIDE_DYLINKER
#ifdef OVERRIDE_DYLINKER
# ifdef TARGET_I386
# define DYLINKER_NAME "/Users/steg/qemu/tests/i386-darwin-env/usr/lib/dyld"
# else
# define DYLINKER_NAME "/usr/lib/dyld"
# endif
#endif
/* XXX: in an include */
struct nlist_extended
{
union {
char *n_name;
long n_strx;
} n_un;
unsigned char n_type;
unsigned char n_sect;
short st_desc;
unsigned long st_value;
unsigned long st_size;
};
/* Print symbols in gdb */
void *macho_text_sect = 0;
int macho_offset = 0;
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh);
#ifdef TARGET_I386
typedef struct mach_i386_thread_state {
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int esp;
unsigned int ss;
unsigned int eflags;
unsigned int eip;
unsigned int cs;
unsigned int ds;
unsigned int es;
unsigned int fs;
unsigned int gs;
} mach_i386_thread_state_t;
void bswap_i386_thread_state(struct mach_i386_thread_state *ts)
{
bswap32s((uint32_t*)&ts->eax);
bswap32s((uint32_t*)&ts->ebx);
bswap32s((uint32_t*)&ts->ecx);
bswap32s((uint32_t*)&ts->edx);
bswap32s((uint32_t*)&ts->edi);
bswap32s((uint32_t*)&ts->esi);
bswap32s((uint32_t*)&ts->ebp);
bswap32s((uint32_t*)&ts->esp);
bswap32s((uint32_t*)&ts->ss);
bswap32s((uint32_t*)&ts->eflags);
bswap32s((uint32_t*)&ts->eip);
bswap32s((uint32_t*)&ts->cs);
bswap32s((uint32_t*)&ts->ds);
bswap32s((uint32_t*)&ts->es);
bswap32s((uint32_t*)&ts->fs);
bswap32s((uint32_t*)&ts->gs);
}
#define target_thread_state mach_i386_thread_state
#define TARGET_CPU_TYPE CPU_TYPE_I386
#define TARGET_CPU_NAME "i386"
#endif
#ifdef TARGET_PPC
struct mach_ppc_thread_state {
unsigned int srr0; /* Instruction address register (PC) */
unsigned int srr1; /* Machine state register (supervisor) */
unsigned int r0;
unsigned int r1;
unsigned int r2;
unsigned int r3;
unsigned int r4;
unsigned int r5;
unsigned int r6;
unsigned int r7;
unsigned int r8;
unsigned int r9;
unsigned int r10;
unsigned int r11;
unsigned int r12;
unsigned int r13;
unsigned int r14;
unsigned int r15;
unsigned int r16;
unsigned int r17;
unsigned int r18;
unsigned int r19;
unsigned int r20;
unsigned int r21;
unsigned int r22;
unsigned int r23;
unsigned int r24;
unsigned int r25;
unsigned int r26;
unsigned int r27;
unsigned int r28;
unsigned int r29;
unsigned int r30;
unsigned int r31;
unsigned int cr; /* Condition register */
unsigned int xer; /* User's integer exception register */
unsigned int lr; /* Link register */
unsigned int ctr; /* Count register */
unsigned int mq; /* MQ register (601 only) */
unsigned int vrsave; /* Vector Save Register */
};
void bswap_ppc_thread_state(struct mach_ppc_thread_state *ts)
{
bswap32s((uint32_t*)&ts->srr0);
bswap32s((uint32_t*)&ts->srr1);
bswap32s((uint32_t*)&ts->r0);
bswap32s((uint32_t*)&ts->r1);
bswap32s((uint32_t*)&ts->r2);
bswap32s((uint32_t*)&ts->r3);
bswap32s((uint32_t*)&ts->r4);
bswap32s((uint32_t*)&ts->r5);
bswap32s((uint32_t*)&ts->r6);
bswap32s((uint32_t*)&ts->r7);
bswap32s((uint32_t*)&ts->r8);
bswap32s((uint32_t*)&ts->r9);
bswap32s((uint32_t*)&ts->r10);
bswap32s((uint32_t*)&ts->r11);
bswap32s((uint32_t*)&ts->r12);
bswap32s((uint32_t*)&ts->r13);
bswap32s((uint32_t*)&ts->r14);
bswap32s((uint32_t*)&ts->r15);
bswap32s((uint32_t*)&ts->r16);
bswap32s((uint32_t*)&ts->r17);
bswap32s((uint32_t*)&ts->r18);
bswap32s((uint32_t*)&ts->r19);
bswap32s((uint32_t*)&ts->r20);
bswap32s((uint32_t*)&ts->r21);
bswap32s((uint32_t*)&ts->r22);
bswap32s((uint32_t*)&ts->r23);
bswap32s((uint32_t*)&ts->r24);
bswap32s((uint32_t*)&ts->r25);
bswap32s((uint32_t*)&ts->r26);
bswap32s((uint32_t*)&ts->r27);
bswap32s((uint32_t*)&ts->r28);
bswap32s((uint32_t*)&ts->r29);
bswap32s((uint32_t*)&ts->r30);
bswap32s((uint32_t*)&ts->r31);
bswap32s((uint32_t*)&ts->cr);
bswap32s((uint32_t*)&ts->xer);
bswap32s((uint32_t*)&ts->lr);
bswap32s((uint32_t*)&ts->ctr);
bswap32s((uint32_t*)&ts->mq);
bswap32s((uint32_t*)&ts->vrsave);
}
#define target_thread_state mach_ppc_thread_state
#define TARGET_CPU_TYPE CPU_TYPE_POWERPC
#define TARGET_CPU_NAME "PowerPC"
#endif
struct target_thread_command {
unsigned long cmd; /* LC_THREAD or LC_UNIXTHREAD */
unsigned long cmdsize; /* total size of this command */
unsigned long flavor; /* flavor of thread state */
unsigned long count; /* count of longs in thread state */
struct target_thread_state state; /* thread state for this flavor */
};
void bswap_tc(struct target_thread_command *tc)
{
bswap32s((uint32_t*)(&tc->flavor));
bswap32s((uint32_t*)&tc->count);
#if defined(TARGET_I386)
bswap_i386_thread_state(&tc->state);
#elif defined(TARGET_PPC)
bswap_ppc_thread_state(&tc->state);
#else
# error unknown TARGET_CPU_TYPE
#endif
}
void bswap_mh(struct mach_header *mh)
{
bswap32s((uint32_t*)(&mh->magic));
bswap32s((uint32_t*)&mh->cputype);
bswap32s((uint32_t*)&mh->cpusubtype);
bswap32s((uint32_t*)&mh->filetype);
bswap32s((uint32_t*)&mh->ncmds);
bswap32s((uint32_t*)&mh->sizeofcmds);
bswap32s((uint32_t*)&mh->flags);
}
void bswap_lc(struct load_command *lc)
{
bswap32s((uint32_t*)&lc->cmd);
bswap32s((uint32_t*)&lc->cmdsize);
}
void bswap_fh(struct fat_header *fh)
{
bswap32s((uint32_t*)&fh->magic);
bswap32s((uint32_t*)&fh->nfat_arch);
}
void bswap_fa(struct fat_arch *fa)
{
bswap32s((uint32_t*)&fa->cputype);
bswap32s((uint32_t*)&fa->cpusubtype);
bswap32s((uint32_t*)&fa->offset);
bswap32s((uint32_t*)&fa->size);
bswap32s((uint32_t*)&fa->align);
}
void bswap_segcmd(struct segment_command *sc)
{
bswap32s((uint32_t*)&sc->vmaddr);
bswap32s((uint32_t*)&sc->vmsize);
bswap32s((uint32_t*)&sc->fileoff);
bswap32s((uint32_t*)&sc->filesize);
bswap32s((uint32_t*)&sc->maxprot);
bswap32s((uint32_t*)&sc->initprot);
bswap32s((uint32_t*)&sc->nsects);
bswap32s((uint32_t*)&sc->flags);
}
void bswap_symtabcmd(struct symtab_command *stc)
{
bswap32s((uint32_t*)&stc->cmd);
bswap32s((uint32_t*)&stc->cmdsize);
bswap32s((uint32_t*)&stc->symoff);
bswap32s((uint32_t*)&stc->nsyms);
bswap32s((uint32_t*)&stc->stroff);
bswap32s((uint32_t*)&stc->strsize);
}
void bswap_sym(struct nlist *n)
{
bswap32s((uint32_t*)&n->n_un.n_strx);
bswap16s((uint16_t*)&n->n_desc);
bswap32s((uint32_t*)&n->n_value);
}
int load_thread(struct mach_header *mh, struct target_thread_command *tc, struct target_pt_regs * regs, int fd, int mh_pos, int need_bswap)
{
int entry;
if(need_bswap)
bswap_tc(tc);
#if defined(TARGET_I386)
entry = tc->state.eip;
DPRINTF(" eax 0x%.8x\n ebx 0x%.8x\n ecx 0x%.8x\n edx 0x%.8x\n edi 0x%.8x\n esi 0x%.8x\n ebp 0x%.8x\n esp 0x%.8x\n ss 0x%.8x\n eflags 0x%.8x\n eip 0x%.8x\n cs 0x%.8x\n ds 0x%.8x\n es 0x%.8x\n fs 0x%.8x\n gs 0x%.8x\n",
tc->state.eax, tc->state.ebx, tc->state.ecx, tc->state.edx, tc->state.edi, tc->state.esi, tc->state.ebp,
tc->state.esp, tc->state.ss, tc->state.eflags, tc->state.eip, tc->state.cs, tc->state.ds, tc->state.es,
tc->state.fs, tc->state.gs );
#define reg_copy(reg) regs->reg = tc->state.reg
if(regs)
{
reg_copy(eax);
reg_copy(ebx);
reg_copy(ecx);
reg_copy(edx);
reg_copy(edi);
reg_copy(esi);
reg_copy(ebp);
reg_copy(esp);
reg_copy(eflags);
reg_copy(eip);
/*
reg_copy(ss);
reg_copy(cs);
reg_copy(ds);
reg_copy(es);
reg_copy(fs);
reg_copy(gs);*/
}
#undef reg_copy
#elif defined(TARGET_PPC)
entry = tc->state.srr0;
#endif
DPRINTF("load_thread: entry 0x%x\n", entry);
return entry;
}
int load_dylinker(struct mach_header *mh, struct dylinker_command *dc, int fd, int mh_pos, int need_bswap)
{
int size;
char * dylinker_name;
size = dc->cmdsize - sizeof(struct dylinker_command);
if(need_bswap)
dylinker_name = (char*)(bswap_32(dc->name.offset)+(int)dc);
else
dylinker_name = (char*)((dc->name.offset)+(int)dc);
#ifdef OVERRIDE_DYLINKER
dylinker_name = DYLINKER_NAME;
#else
if(asprintf(&dylinker_name, "%s%s", interp_prefix, dylinker_name) == -1)
qerror("can't allocate the new dylinker name\n");
#endif
DPRINTF("dylinker_name %s\n", dylinker_name);
return load_object(dylinker_name, NULL, NULL);
}
int load_segment(struct mach_header *mh, struct segment_command *sc, int fd, int mh_pos, int need_bswap, int fixed, int slide)
{
unsigned long addr = sc->vmaddr;
unsigned long size = sc->filesize;
unsigned long error = 0;
if(need_bswap)
bswap_segcmd(sc);
if(sc->vmaddr == 0)
{
DPRINTF("load_segment: sc->vmaddr == 0 returning\n");
return -1;
}
if (strcmp(sc->segname, "__PAGEZERO") == 0)
{
DPRINTF("load_segment: __PAGEZERO returning\n");
return -1;
}
/* Right now mmap memory */
/* XXX: should check to see that the space is free, because MAP_FIXED is dangerous */
DPRINTF("load_segment: mmaping %s to 0x%x-(0x%x|0x%x) + 0x%x\n", sc->segname, sc->vmaddr, sc->filesize, sc->vmsize, slide);
if(sc->filesize > 0)
{
int opt = 0;
if(fixed)
opt |= MAP_FIXED;
DPRINTF("sc->vmaddr 0x%x slide 0x%x add 0x%x\n", slide, sc->vmaddr, sc->vmaddr+slide);
addr = target_mmap(sc->vmaddr+slide, sc->filesize, sc->initprot, opt, fd, mh_pos + sc->fileoff);
if(addr==-1)
qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
error = addr-sc->vmaddr;
}
else
{
addr = sc->vmaddr+slide;
error = slide;
}
if(sc->vmsize > sc->filesize)
{
addr += sc->filesize;
size = sc->vmsize-sc->filesize;
addr = target_mmap(addr, size, sc->initprot, MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if(addr==-1)
qerror("load_segment: can't mmap at 0x%x\n", sc->vmaddr+slide);
}
return error;
}
void *load_data(int fd, long offset, unsigned int size)
{
char *data;
data = malloc(size);
if (!data)
return NULL;
lseek(fd, offset, SEEK_SET);
if (read(fd, data, size) != size) {
free(data);
return NULL;
}
return data;
}
/* load a mach-o object file */
int load_object(const char *filename, struct target_pt_regs * regs, void ** mh)
{
int need_bswap = 0;
int entry_point = 0;
int dyld_entry_point = 0;
int slide, mmapfixed;
int fd;
struct load_command *lcmds, *lc;
int is_fat = 0;
unsigned int i, magic;
int mach_hdr_pos = 0;
struct mach_header mach_hdr;
/* for symbol lookup with -d flag. */
struct symtab_command * symtabcmd = 0;
struct nlist_extended *symtab, *sym;
struct nlist *symtab_std, *syment;
char *strtab;
fd = open(filename, O_RDONLY);
if (fd < 0)
qerror("can't open file '%s'", filename);
/* Read magic header. */
if (read(fd, &magic, sizeof (magic)) != sizeof (magic))
qerror("unable to read Magic of '%s'", filename);
/* Check Mach identification. */
if(magic == MH_MAGIC)
{
is_fat = 0;
need_bswap = 0;
} else if (magic == MH_CIGAM)
{
is_fat = 0;
need_bswap = 1;
} else if (magic == FAT_MAGIC)
{
is_fat = 1;
need_bswap = 0;
} else if (magic == FAT_CIGAM)
{
is_fat = 1;
need_bswap = 1;
}
else
qerror("Not a Mach-O file.", filename);
DPRINTF("loading %s %s...\n", filename, is_fat ? "[FAT]": "[REGULAR]");
if(is_fat)
{
int found = 0;
struct fat_header fh;
struct fat_arch *fa;
lseek(fd, 0, SEEK_SET);
/* Read Fat header. */
if (read(fd, &fh, sizeof (fh)) != sizeof (fh))
qerror("unable to read file header");
if(need_bswap)
bswap_fh(&fh);
/* Read Fat Arch. */
fa = malloc(sizeof(struct fat_arch)*fh.nfat_arch);
if (read(fd, fa, sizeof(struct fat_arch)*fh.nfat_arch) != sizeof(struct fat_arch)*fh.nfat_arch)
qerror("unable to read file header");
for( i = 0; i < fh.nfat_arch; i++, fa++)
{
if(need_bswap)
bswap_fa(fa);
if(fa->cputype == TARGET_CPU_TYPE)
{
mach_hdr_pos = fa->offset;
lseek(fd, mach_hdr_pos, SEEK_SET);
/* Read Mach header. */
if (read(fd, &mach_hdr, sizeof(struct mach_header)) != sizeof (struct mach_header))
qerror("unable to read file header");
if(mach_hdr.magic == MH_MAGIC)
need_bswap = 0;
else if (mach_hdr.magic == MH_CIGAM)
need_bswap = 1;
else
qerror("Invalid mach header in Fat Mach-O File");
found = 1;
break;
}
}
if(!found)
qerror("%s: No %s CPU found in FAT Header", filename, TARGET_CPU_NAME);
}
else
{
lseek(fd, 0, SEEK_SET);
/* Read Mach header */
if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
qerror("%s: unable to read file header", filename);
}
if(need_bswap)
bswap_mh(&mach_hdr);
if ((mach_hdr.cputype) != TARGET_CPU_TYPE)
qerror("%s: Unsupported CPU 0x%x (only 0x%x(%s) supported)", filename, mach_hdr.cputype, TARGET_CPU_TYPE, TARGET_CPU_NAME);
switch(mach_hdr.filetype)
{
case MH_EXECUTE: break;
case MH_FVMLIB:
case MH_DYLIB:
case MH_DYLINKER: break;
default:
qerror("%s: Unsupported Mach type (0x%x)", filename, mach_hdr.filetype);
}
/* read segment headers */
lcmds = malloc(mach_hdr.sizeofcmds);
if(read(fd, lcmds, mach_hdr.sizeofcmds) != mach_hdr.sizeofcmds)
qerror("%s: unable to read load_command", filename);
slide = 0;
mmapfixed = 0;
for(i=0, lc = lcmds; i < (mach_hdr.ncmds) ; i++)
{
if(need_bswap)
bswap_lc(lc);
switch(lc->cmd)
{
case LC_SEGMENT:
/* The main_exe can't be relocated */
if(mach_hdr.filetype == MH_EXECUTE)
mmapfixed = 1;
slide = load_segment(&mach_hdr, (struct segment_command*)lc, fd, mach_hdr_pos, need_bswap, mmapfixed, slide);
/* other segment must be mapped according to slide exactly, if load_segment did something */
if(slide != -1)
mmapfixed = 1;
else
slide = 0; /* load_segment didn't map the segment */
if(mach_hdr.filetype == MH_EXECUTE && slide != 0)
qerror("%s: Warning executable can't be mapped at the right address (offset: 0x%x)\n", filename, slide);
if(strcmp(((struct segment_command*)(lc))->segname, "__TEXT") == 0)
{
/* Text section */
if(mach_hdr.filetype == MH_EXECUTE)
{
/* return the mach_header */
*mh = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
}
else
{
/* it is dyld save the section for gdb, we will be interested in dyld symbol
while debuging */
macho_text_sect = (void*)(((struct segment_command*)(lc))->vmaddr + slide);
macho_offset = slide;
}
}
break;
case LC_LOAD_DYLINKER:
dyld_entry_point = load_dylinker( &mach_hdr, (struct dylinker_command*)lc, fd, mach_hdr_pos, need_bswap );
break;
case LC_LOAD_DYLIB:
/* dyld will do that for us */
break;
case LC_THREAD:
case LC_UNIXTHREAD:
{
struct target_pt_regs * _regs;
if(mach_hdr.filetype == MH_DYLINKER)
_regs = regs;
else
_regs = 0;
entry_point = load_thread( &mach_hdr, (struct target_thread_command*)lc, _regs, fd, mach_hdr_pos, need_bswap );
}
break;
case LC_SYMTAB:
/* Save the symtab and strtab */
symtabcmd = (struct symtab_command *)lc;
break;
case LC_ID_DYLINKER:
case LC_ID_DYLIB:
case LC_UUID:
case LC_DYSYMTAB:
case LC_TWOLEVEL_HINTS:
case LC_PREBIND_CKSUM:
case LC_SUB_LIBRARY:
break;
default: fprintf(stderr, "warning: unknown command 0x%x in '%s'\n", lc->cmd, filename);
}
lc = (struct load_command*)((int)(lc)+(lc->cmdsize));
}
if(symtabcmd)
{
if(need_bswap)
bswap_symtabcmd(symtabcmd);
symtab_std = load_data(fd, symtabcmd->symoff+mach_hdr_pos, symtabcmd->nsyms * sizeof(struct nlist));
strtab = load_data(fd, symtabcmd->stroff+mach_hdr_pos, symtabcmd->strsize);
symtab = malloc(sizeof(struct nlist_extended) * symtabcmd->nsyms);
if(need_bswap)
{
for(i = 0, syment = symtab_std; i < symtabcmd->nsyms; i++, syment++)
bswap_sym(syment);
}
for(i = 0, sym = symtab, syment = symtab_std; i < symtabcmd->nsyms; i++, sym++, syment++)
{
struct nlist *sym_follow, *sym_next = 0;
unsigned int j;
memset(sym, 0, sizeof(*sym));
sym->n_type = syment->n_type;
if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
continue;
memcpy(sym, syment, sizeof(*syment));
/* Find the following symbol in order to get the current symbol size */
for(j = 0, sym_follow = symtab_std; j < symtabcmd->nsyms; j++, sym_follow++) {
if ( sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
continue;
if(!sym_next) {
sym_next = sym_follow;
continue;
}
if(!(sym_next->n_value > sym_follow->n_value))
continue;
sym_next = sym_follow;
}
if(sym_next)
sym->st_size = sym_next->n_value - sym->st_value;
else
sym->st_size = 10; /* XXX: text_sec_hdr->size + text_sec_hdr->offset - sym->st_value; */
sym->st_value += slide;
}
free((void*)symtab_std);
{
DPRINTF("saving symtab of %s (%d symbol(s))\n", filename, symtabcmd->nsyms);
struct syminfo *s;
s = malloc(sizeof(*s));
s->disas_symtab = symtab;
s->disas_strtab = strtab;
s->disas_num_syms = symtabcmd->nsyms;
s->next = syminfos;
syminfos = s;
}
}
close(fd);
if(mach_hdr.filetype == MH_EXECUTE && dyld_entry_point)
return dyld_entry_point;
else
return entry_point+slide;
}
extern unsigned long stack_size;
unsigned long setup_arg_pages(void * mh, char ** argv, char ** env)
{
unsigned long stack_base, error, size;
int i;
int * stack;
int argc, envc;
/* Create enough stack to hold everything. If we don't use
* it for args, we'll use it for something else...
*/
size = stack_size;
error = target_mmap(0,
size + qemu_host_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (error == -1)
qerror("stk mmap");
/* we reserve one extra page at the top of the stack as guard */
target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
stack_base = error + size;
stack = (void*)stack_base;
/*
* | STRING AREA |
* +-------------+
* | 0 |
* +-------------+
* | apple[n] |
* +-------------+
* :
* +-------------+
* | apple[0] |
* +-------------+
* | 0 |
* +-------------+
* | env[n] |
* +-------------+
* :
* :
* +-------------+
* | env[0] |
* +-------------+
* | 0 |
* +-------------+
* | arg[argc-1] |
* +-------------+
* :
* :
* +-------------+
* | arg[0] |
* +-------------+
* | argc |
* +-------------+
* sp-> | mh | address of where the a.out's file offset 0 is in memory
* +-------------+
*/
/* Construct the stack Stack grows down */
stack--;
/* XXX: string should go up there */
*stack = 0;
stack--;
/* Push the absolute path of our executable */
DPRINTF("pushing apple %s (0x%x)\n", (char*)argv[0], (int)argv[0]);
stl(stack, (int) argv[0]);
stack--;
stl(stack, 0);
stack--;
/* Get envc */
for(envc = 0; env[envc]; envc++);
for(i = envc-1; i >= 0; i--)
{
DPRINTF("pushing env %s (0x%x)\n", (char*)env[i], (int)env[i]);
stl(stack, (int)env[i]);
stack--;
/* XXX: remove that when string will be on top of the stack */
page_set_flags((int)env[i], (int)(env[i]+strlen(env[i])), PROT_READ | PAGE_VALID);
}
/* Add on the stack the interp_prefix chosen if so */
if(interp_prefix[0])
{
char *dyld_root;
asprintf(&dyld_root, "DYLD_ROOT_PATH=%s", interp_prefix);
page_set_flags((int)dyld_root, (int)(dyld_root+strlen(interp_prefix)+1), PROT_READ | PAGE_VALID);
stl(stack, (int)dyld_root);
stack--;
}
#ifdef DONT_USE_DYLD_SHARED_MAP
{
char *shared_map_mode;
asprintf(&shared_map_mode, "DYLD_SHARED_REGION=avoid");
page_set_flags((int)shared_map_mode, (int)(shared_map_mode+strlen(shared_map_mode)+1), PROT_READ | PAGE_VALID);
stl(stack, (int)shared_map_mode);
stack--;
}
#endif
#ifdef ACTIVATE_DYLD_TRACE
char * extra_env_static[] = {"DYLD_DEBUG_TRACE=yes",
"DYLD_PREBIND_DEBUG=3", "DYLD_UNKNOW_TRACE=yes",
"DYLD_PRINT_INITIALIZERS=yes",
"DYLD_PRINT_SEGMENTS=yes", "DYLD_PRINT_REBASINGS=yes", "DYLD_PRINT_BINDINGS=yes", "DYLD_PRINT_INITIALIZERS=yes", "DYLD_PRINT_WARNINGS=yes" };
char ** extra_env = malloc(sizeof(extra_env_static));
bcopy(extra_env_static, extra_env, sizeof(extra_env_static));
page_set_flags((int)extra_env, (int)((void*)extra_env+sizeof(extra_env_static)), PROT_READ | PAGE_VALID);
for(i = 0; i<9; i++)
{
DPRINTF("pushing (extra) env %s (0x%x)\n", (char*)extra_env[i], (int)extra_env[i]);
stl(stack, (int) extra_env[i]);
stack--;
}
#endif
stl(stack, 0);
stack--;
/* Get argc */
for(argc = 0; argv[argc]; argc++);
for(i = argc-1; i >= 0; i--)
{
DPRINTF("pushing arg %s (0x%x)\n", (char*)argv[i], (int)argv[i]);
stl(stack, (int) argv[i]);
stack--;
/* XXX: remove that when string will be on top of the stack */
page_set_flags((int)argv[i], (int)(argv[i]+strlen(argv[i])), PROT_READ | PAGE_VALID);
}
DPRINTF("pushing argc %d\n", argc);
stl(stack, argc);
stack--;
DPRINTF("pushing mh 0x%x\n", (int)mh);
stl(stack, (int) mh);
/* Stack points on the mh */
return (unsigned long)stack;
}
int mach_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs)
{
int entrypoint, stack;
void * mh; /* the Mach Header that will be used by dyld */
DPRINTF("mach_exec at 0x%x\n", (int)mach_exec);
entrypoint = load_object(filename, regs, &mh);
stack = setup_arg_pages(mh, argv, envp);
#if defined(TARGET_I386)
regs->eip = entrypoint;
regs->esp = stack;
#elif defined(TARGET_PPC)
regs->nip = entrypoint;
regs->gpr[1] = stack;
#endif
DPRINTF("mach_exec returns eip set to 0x%x esp 0x%x mh 0x%x\n", entrypoint, stack, (int)mh);
if(!entrypoint)
qerror("%s: no entry point!\n", filename);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,409 +0,0 @@
/*
* mmap support for qemu
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include "qemu.h"
//#define DEBUG_MMAP
/* NOTE: all the constants are the HOST ones */
int target_mprotect(unsigned long start, unsigned long len, int prot)
{
unsigned long end, host_start, host_end, addr;
int prot1, ret;
#ifdef DEBUG_MMAP
printf("mprotect: start=0x%lx len=0x%lx prot=%c%c%c\n", start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
#endif
if ((start & ~TARGET_PAGE_MASK) != 0)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
if (end < start)
return -EINVAL;
if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
return -EINVAL;
if (len == 0)
return 0;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
/* handle host page containing start */
prot1 = prot;
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
if (host_end == host_start + qemu_host_page_size) {
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
end = host_end;
}
ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_start += qemu_host_page_size;
}
if (end < host_end) {
prot1 = prot;
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_end -= qemu_host_page_size;
}
/* handle the pages in the middle */
if (host_start < host_end) {
ret = mprotect((void *)host_start, host_end - host_start, prot);
if (ret != 0)
return ret;
}
page_set_flags(start, start + len, prot | PAGE_VALID);
return 0;
}
/* map an incomplete host page */
int mmap_frag(unsigned long host_start,
unsigned long start, unsigned long end,
int prot, int flags, int fd, unsigned long offset)
{
unsigned long host_end, ret, addr;
int prot1, prot_new;
host_end = host_start + qemu_host_page_size;
/* get the protection of the target pages outside the mapping */
prot1 = 0;
for(addr = host_start; addr < host_end; addr++) {
if (addr < start || addr >= end)
prot1 |= page_get_flags(addr);
}
if (prot1 == 0) {
/* no page was there, so we allocate one */
ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
flags | MAP_ANONYMOUS, -1, 0);
if (ret == -1)
return ret;
}
prot1 &= PAGE_BITS;
prot_new = prot | prot1;
if (!(flags & MAP_ANONYMOUS)) {
/* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
#ifndef __APPLE__
if ((flags & MAP_TYPE) == MAP_SHARED &&
#else
if ((flags & MAP_SHARED) &&
#endif
(prot & PROT_WRITE))
return -1;
/* adjust protection to be able to read */
if (!(prot1 & PROT_WRITE))
mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE);
/* read the corresponding file data */
pread(fd, (void *)start, end - start, offset);
/* put final protection */
if (prot_new != (prot1 | PROT_WRITE))
mprotect((void *)host_start, qemu_host_page_size, prot_new);
} else {
/* just update the protection */
if (prot_new != prot1) {
mprotect((void *)host_start, qemu_host_page_size, prot_new);
}
}
return 0;
}
/* NOTE: all the constants are the HOST ones */
long target_mmap(unsigned long start, unsigned long len, int prot,
int flags, int fd, unsigned long offset)
{
unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len;
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
static unsigned long last_start = 0x40000000;
#endif
#ifdef DEBUG_MMAP
{
printf("mmap: start=0x%lx len=0x%lx prot=%c%c%c flags=",
start, len,
prot & PROT_READ ? 'r' : '-',
prot & PROT_WRITE ? 'w' : '-',
prot & PROT_EXEC ? 'x' : '-');
if (flags & MAP_FIXED)
printf("MAP_FIXED ");
if (flags & MAP_ANONYMOUS)
printf("MAP_ANON ");
#ifndef MAP_TYPE
# define MAP_TYPE 0x3
#endif
switch(flags & MAP_TYPE) {
case MAP_PRIVATE:
printf("MAP_PRIVATE ");
break;
case MAP_SHARED:
printf("MAP_SHARED ");
break;
default:
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
break;
}
printf("fd=%d offset=%lx\n", fd, offset);
}
#endif
if (offset & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
if (len == 0)
return start;
host_start = start & qemu_host_page_mask;
if (!(flags & MAP_FIXED)) {
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
/* tell the kernel to search at the same place as i386 */
if (host_start == 0) {
host_start = last_start;
last_start += HOST_PAGE_ALIGN(len);
}
#endif
if (qemu_host_page_size != qemu_real_host_page_size) {
/* NOTE: this code is only for debugging with '-p' option */
/* reserve a memory area */
host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE;
host_start = (long)mmap((void *)host_start, host_len, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (host_start == -1)
return host_start;
host_end = host_start + host_len;
start = HOST_PAGE_ALIGN(host_start);
end = start + HOST_PAGE_ALIGN(len);
if (start > host_start)
munmap((void *)host_start, start - host_start);
if (end < host_end)
munmap((void *)end, host_end - end);
/* use it as a fixed mapping */
flags |= MAP_FIXED;
} else {
/* if not fixed, no need to do anything */
host_offset = offset & qemu_host_page_mask;
host_len = len + offset - host_offset;
start = (long)mmap((void *)host_start, host_len,
prot, flags, fd, host_offset);
if (start == -1)
return start;
/* update start so that it points to the file position at 'offset' */
if (!(flags & MAP_ANONYMOUS))
start += offset - host_offset;
goto the_end1;
}
}
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
end = start + len;
host_end = HOST_PAGE_ALIGN(end);
/* worst case: we cannot map the file because the offset is not
aligned, so we read it */
if (!(flags & MAP_ANONYMOUS) &&
(offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
/* msync() won't work here, so we return an error if write is
possible while it is a shared mapping */
#ifndef __APPLE__
if ((flags & MAP_TYPE) == MAP_SHARED &&
#else
if ((flags & MAP_SHARED) &&
#endif
(prot & PROT_WRITE))
return -EINVAL;
retaddr = target_mmap(start, len, prot | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if (retaddr == -1)
return retaddr;
pread(fd, (void *)start, len, offset);
if (!(prot & PROT_WRITE)) {
ret = target_mprotect(start, len, prot);
if (ret != 0)
return ret;
}
goto the_end;
}
/* handle the start of the mapping */
if (start > host_start) {
if (host_end == host_start + qemu_host_page_size) {
/* one single host page */
ret = mmap_frag(host_start, start, end,
prot, flags, fd, offset);
if (ret == -1)
return ret;
goto the_end1;
}
ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
prot, flags, fd, offset);
if (ret == -1)
return ret;
host_start += qemu_host_page_size;
}
/* handle the end of the mapping */
if (end < host_end) {
ret = mmap_frag(host_end - qemu_host_page_size,
host_end - qemu_host_page_size, host_end,
prot, flags, fd,
offset + host_end - qemu_host_page_size - start);
if (ret == -1)
return ret;
host_end -= qemu_host_page_size;
}
/* map the middle (easier) */
if (host_start < host_end) {
unsigned long offset1;
if (flags & MAP_ANONYMOUS)
offset1 = 0;
else
offset1 = offset + host_start - start;
ret = (long)mmap((void *)host_start, host_end - host_start,
prot, flags, fd, offset1);
if (ret == -1)
return ret;
}
the_end1:
page_set_flags(start, start + len, prot | PAGE_VALID);
the_end:
#ifdef DEBUG_MMAP
printf("target_mmap: ret=0x%lx\n", (long)start);
page_dump(stdout);
printf("\n");
#endif
return start;
}
int target_munmap(unsigned long start, unsigned long len)
{
unsigned long end, host_start, host_end, addr;
int prot, ret;
#ifdef DEBUG_MMAP
printf("munmap: start=0x%lx len=0x%lx\n", start, len);
#endif
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
if (len == 0)
return -EINVAL;
end = start + len;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
/* handle host page containing start */
prot = 0;
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (host_end == host_start + qemu_host_page_size) {
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
end = host_end;
}
if (prot != 0)
host_start += qemu_host_page_size;
}
if (end < host_end) {
prot = 0;
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (prot != 0)
host_end -= qemu_host_page_size;
}
/* unmap what we can */
if (host_start < host_end) {
ret = munmap((void *)host_start, host_end - host_start);
if (ret != 0)
return ret;
}
page_set_flags(start, start + len, 0);
return 0;
}
/* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED
blocks which have been allocated starting on a host page */
long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_size, unsigned long flags,
unsigned long new_addr)
{
#ifndef __APPLE__
/* XXX: use 5 args syscall */
new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags);
if (new_addr == -1)
return new_addr;
prot = page_get_flags(old_addr);
page_set_flags(old_addr, old_addr + old_size, 0);
page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID);
return new_addr;
#else
qerror("target_mremap: unsupported\n");
#endif
}
int target_msync(unsigned long start, unsigned long len, int flags)
{
unsigned long end;
if (start & ~TARGET_PAGE_MASK)
return -EINVAL;
len = TARGET_PAGE_ALIGN(len);
end = start + len;
if (end < start)
return -EINVAL;
if (end == start)
return 0;
start &= qemu_host_page_mask;
return msync((void *)start, end - start, flags);
}

View file

@ -1,178 +0,0 @@
#ifndef GEMU_H
#define GEMU_H
#include <signal.h>
#include <string.h>
#include "cpu.h"
#include "thunk.h"
#include "gdbstub.h"
typedef siginfo_t target_siginfo_t;
#define target_sigaction sigaction
#ifdef TARGET_I386
struct target_pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
struct target_sigcontext {
int sc_onstack;
int sc_mask;
int sc_eax;
int sc_ebx;
int sc_ecx;
int sc_edx;
int sc_edi;
int sc_esi;
int sc_ebp;
int sc_esp;
int sc_ss;
int sc_eflags;
int sc_eip;
int sc_cs;
int sc_ds;
int sc_es;
int sc_fs;
int sc_gs;
};
#define __USER_CS (0x17)
#define __USER_DS (0x1F)
#elif defined(TARGET_PPC)
struct target_pt_regs {
unsigned long gpr[32];
unsigned long nip;
unsigned long msr;
unsigned long orig_gpr3; /* Used for restarting system calls */
unsigned long ctr;
unsigned long link;
unsigned long xer;
unsigned long ccr;
unsigned long mq; /* 601 only (not used at present) */
/* Used on APUS to hold IPL value. */
unsigned long trap; /* Reason for being here */
unsigned long dar; /* Fault registers */
unsigned long dsisr;
unsigned long result; /* Result of a system call */
};
struct target_sigcontext {
int sc_onstack; /* sigstack state to restore */
int sc_mask; /* signal mask to restore */
int sc_ir; /* pc */
int sc_psw; /* processor status word */
int sc_sp; /* stack pointer if sc_regs == NULL */
void *sc_regs; /* (kernel private) saved state */
};
#endif
typedef struct TaskState {
struct TaskState *next;
int used; /* non zero if used */
uint8_t stack[0];
} __attribute__((aligned(16))) TaskState;
void syscall_init(void);
long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
long do_unix_syscall(void *cpu_env, int num);
int do_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact);
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
void qerror(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags);
extern CPUArchState *global_env;
void cpu_loop(CPUArchState *env);
void init_paths(const char *prefix);
const char *path(const char *pathname);
#include "qemu-log.h"
/* commpage.c */
void commpage_init(void);
void do_commpage(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8);
/* signal.c */
void process_pending_signals(void *cpu_env);
void signal_init(void);
int queue_signal(int sig, target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
long do_sigreturn(CPUArchState *env, int num);
/* machload.c */
int mach_exec(const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs);
/* mmap.c */
int target_mprotect(unsigned long start, unsigned long len, int prot);
long target_mmap(unsigned long start, unsigned long len, int prot,
int flags, int fd, unsigned long offset);
int target_munmap(unsigned long start, unsigned long len);
long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_size, unsigned long flags,
unsigned long new_addr);
int target_msync(unsigned long start, unsigned long len, int flags);
/* user access */
/* XXX: todo protect every memory access */
#define lock_user(x,y,z) (void*)(x)
#define unlock_user(x,y,z)
/* Mac OS X ABI arguments processing */
#ifdef TARGET_I386
static inline uint32_t get_int_arg(int *i, CPUX86State *cpu_env)
{
uint32_t *args = (uint32_t*)(cpu_env->regs[R_ESP] + 4 + *i);
*i+=4;
return tswap32(*args);
}
static inline uint64_t get_int64_arg(int *i, CPUX86State *cpu_env)
{
uint64_t *args = (uint64_t*)(cpu_env->regs[R_ESP] + 4 + *i);
*i+=8;
return tswap64(*args);
}
#elif defined(TARGET_PPC)
static inline uint32_t get_int_arg(int *i, CPUPPCState *cpu_env)
{
/* XXX: won't work when args goes on stack after gpr10 */
uint32_t args = (uint32_t)(cpu_env->gpr[3+(*i & 0xff)/4]);
*i+=4;
return tswap32(args);
}
static inline uint64_t get_int64_arg(int *i, CPUPPCState *cpu_env)
{
/* XXX: won't work when args goes on stack after gpr10 */
uint64_t args = (uint64_t)(cpu_env->fpr[1+(*i >> 8)/8]);
*i+=(8 << 8) + 8;
return tswap64(args);
}
#endif
#endif

View file

@ -1,452 +0,0 @@
/*
* Emulation of Linux signals
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ucontext.h>
#ifdef __ia64__
#undef uc_mcontext
#undef uc_sigmask
#undef uc_stack
#undef uc_link
#endif
#include "qemu.h"
#include "qemu-common.h"
#define DEBUG_SIGNAL
#define MAX_SIGQUEUE_SIZE 1024
struct sigqueue {
struct sigqueue *next;
target_siginfo_t info;
};
struct emulated_sigaction {
struct target_sigaction sa;
int pending; /* true if signal is pending */
struct sigqueue *first;
struct sigqueue info; /* in order to always have memory for the
first signal, we put it here */
};
static struct sigaltstack target_sigaltstack_used = {
0, 0, SA_DISABLE
};
static struct emulated_sigaction sigact_table[NSIG];
static struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */
static struct sigqueue *first_free; /* first free siginfo queue entry */
static int signal_pending; /* non zero if a signal may be pending */
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc);
static inline int host_to_target_signal(int sig)
{
return sig;
}
static inline int target_to_host_signal(int sig)
{
return sig;
}
/* siginfo conversion */
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info)
{
}
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo)
{
}
void signal_init(void)
{
struct sigaction act;
int i;
/* set all host signal handlers. ALL signals are blocked during
the handlers to serialize them. */
sigfillset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = host_signal_handler;
for(i = 1; i < NSIG; i++) {
sigaction(i, &act, NULL);
}
memset(sigact_table, 0, sizeof(sigact_table));
first_free = &sigqueue_table[0];
for(i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++)
sigqueue_table[i].next = &sigqueue_table[i + 1];
sigqueue_table[MAX_SIGQUEUE_SIZE - 1].next = NULL;
}
/* signal queue handling */
static inline struct sigqueue *alloc_sigqueue(void)
{
struct sigqueue *q = first_free;
if (!q)
return NULL;
first_free = q->next;
return q;
}
static inline void free_sigqueue(struct sigqueue *q)
{
q->next = first_free;
first_free = q;
}
/* abort execution with signal */
void QEMU_NORETURN force_sig(int sig)
{
int host_sig;
host_sig = target_to_host_signal(sig);
fprintf(stderr, "qemu: uncaught target signal %d (%s) - exiting\n",
sig, strsignal(host_sig));
_exit(-host_sig);
}
/* queue a signal so that it will be send to the virtual CPU as soon
as possible */
int queue_signal(int sig, target_siginfo_t *info)
{
struct emulated_sigaction *k;
struct sigqueue *q, **pq;
target_ulong handler;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "queue_signal: sig=%d\n",
sig);
#endif
k = &sigact_table[sig - 1];
handler = (target_ulong)k->sa.sa_handler;
if (handler == SIG_DFL) {
/* default handler : ignore some signal. The other are fatal */
if (sig != SIGCHLD &&
sig != SIGURG &&
sig != SIGWINCH) {
force_sig(sig);
} else {
return 0; /* indicate ignored */
}
} else if (handler == host_to_target_signal(SIG_IGN)) {
/* ignore signal */
return 0;
} else if (handler == host_to_target_signal(SIG_ERR)) {
force_sig(sig);
} else {
pq = &k->first;
if (!k->pending) {
/* first signal */
q = &k->info;
} else {
q = alloc_sigqueue();
if (!q)
return -EAGAIN;
while (*pq != NULL)
pq = &(*pq)->next;
}
*pq = q;
q->info = *info;
q->next = NULL;
k->pending = 1;
/* signal that a new signal is pending */
signal_pending = 1;
return 1; /* indicates that the signal was queued */
}
}
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
int sig;
target_siginfo_t tinfo;
/* the CPU emulator uses some host signals to detect exceptions,
we we forward to it some signals */
if (host_signum == SIGSEGV || host_signum == SIGBUS) {
if (cpu_signal_handler(host_signum, (void*)info, puc))
return;
}
/* get target signal number */
sig = host_to_target_signal(host_signum);
if (sig < 1 || sig > NSIG)
return;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "qemu: got signal %d\n", sig);
#endif
if (queue_signal(sig, &tinfo) == 1) {
/* interrupt the virtual CPU as soon as possible */
cpu_exit(global_env);
}
}
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
{
/* XXX: test errors */
if(oss)
{
oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp);
oss->ss_size = tswap32(target_sigaltstack_used.ss_size);
oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags);
}
if(ss)
{
target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp);
target_sigaltstack_used.ss_size = tswap32(ss->ss_size);
target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags);
}
return 0;
}
int do_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact)
{
struct emulated_sigaction *k;
struct sigaction act1;
int host_sig;
if (sig < 1 || sig > NSIG)
return -EINVAL;
k = &sigact_table[sig - 1];
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
if (oact) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction 1 sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
oact->sa_handler = tswapl(k->sa.sa_handler);
oact->sa_flags = tswapl(k->sa.sa_flags);
oact->sa_mask = tswapl(k->sa.sa_mask);
}
if (act) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction handler 0x%x flag 0x%x mask 0x%x\n",
act->sa_handler, act->sa_flags, act->sa_mask);
#endif
k->sa.sa_handler = tswapl(act->sa_handler);
k->sa.sa_flags = tswapl(act->sa_flags);
k->sa.sa_mask = tswapl(act->sa_mask);
/* we update the host signal state */
host_sig = target_to_host_signal(sig);
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction handler going to call sigaction\n");
#endif
sigfillset(&act1.sa_mask);
act1.sa_flags = SA_SIGINFO;
if (k->sa.sa_flags & SA_RESTART)
act1.sa_flags |= SA_RESTART;
/* NOTE: it is important to update the host kernel signal
ignore state to avoid getting unexpected interrupted
syscalls */
if (k->sa.sa_handler == SIG_IGN) {
act1.sa_sigaction = (void *)SIG_IGN;
} else if (k->sa.sa_handler == SIG_DFL) {
act1.sa_sigaction = (void *)SIG_DFL;
} else {
act1.sa_sigaction = host_signal_handler;
}
sigaction(host_sig, &act1, NULL);
}
}
return 0;
}
#ifdef TARGET_I386
static inline void *
get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size)
{
/* XXX Fix that */
if(target_sigaltstack_used.ss_flags & SA_DISABLE)
{
int esp;
/* Default to using normal stack */
esp = env->regs[R_ESP];
return (void *)((esp - frame_size) & -8ul);
}
else
{
return target_sigaltstack_used.ss_sp;
}
}
static void setup_frame(int sig, struct emulated_sigaction *ka,
void *set, CPUX86State *env)
{
void *frame;
fprintf(stderr, "setup_frame %d\n", sig);
frame = get_sigframe(ka, env, sizeof(*frame));
/* Set up registers for signal handler */
env->regs[R_ESP] = (unsigned long) frame;
env->eip = (unsigned long) ka->sa.sa_handler;
env->eflags &= ~TF_MASK;
return;
give_sigsegv:
if (sig == SIGSEGV)
ka->sa.sa_handler = SIG_DFL;
force_sig(SIGSEGV /* , current */);
}
long do_sigreturn(CPUX86State *env, int num)
{
int i = 0;
struct target_sigcontext *scp = get_int_arg(&i, env);
/* XXX Get current signal number */
/* XXX Adjust accordin to sc_onstack, sc_mask */
if(tswapl(scp->sc_onstack) & 0x1)
target_sigaltstack_used.ss_flags |= ~SA_DISABLE;
else
target_sigaltstack_used.ss_flags &= SA_DISABLE;
int set = tswapl(scp->sc_eax);
sigprocmask(SIG_SETMASK, &set, NULL);
fprintf(stderr, "do_sigreturn: partially implemented %x EAX:%x EBX:%x\n", scp->sc_mask, tswapl(scp->sc_eax), tswapl(scp->sc_ebx));
fprintf(stderr, "ECX:%x EDX:%x EDI:%x\n", scp->sc_ecx, tswapl(scp->sc_edx), tswapl(scp->sc_edi));
fprintf(stderr, "EIP:%x\n", tswapl(scp->sc_eip));
env->regs[R_EAX] = tswapl(scp->sc_eax);
env->regs[R_EBX] = tswapl(scp->sc_ebx);
env->regs[R_ECX] = tswapl(scp->sc_ecx);
env->regs[R_EDX] = tswapl(scp->sc_edx);
env->regs[R_EDI] = tswapl(scp->sc_edi);
env->regs[R_ESI] = tswapl(scp->sc_esi);
env->regs[R_EBP] = tswapl(scp->sc_ebp);
env->regs[R_ESP] = tswapl(scp->sc_esp);
env->segs[R_SS].selector = (void*)tswapl(scp->sc_ss);
env->eflags = tswapl(scp->sc_eflags);
env->eip = tswapl(scp->sc_eip);
env->segs[R_CS].selector = (void*)tswapl(scp->sc_cs);
env->segs[R_DS].selector = (void*)tswapl(scp->sc_ds);
env->segs[R_ES].selector = (void*)tswapl(scp->sc_es);
env->segs[R_FS].selector = (void*)tswapl(scp->sc_fs);
env->segs[R_GS].selector = (void*)tswapl(scp->sc_gs);
/* Again, because our caller's caller will reset EAX */
return env->regs[R_EAX];
}
#else
static void setup_frame(int sig, struct emulated_sigaction *ka,
void *set, CPUArchState *env)
{
fprintf(stderr, "setup_frame: not implemented\n");
}
long do_sigreturn(CPUArchState *env, int num)
{
int i = 0;
struct target_sigcontext *scp = get_int_arg(&i, env);
fprintf(stderr, "do_sigreturn: not implemented\n");
return -ENOSYS;
}
#endif
void process_pending_signals(void *cpu_env)
{
struct emulated_sigaction *k;
struct sigqueue *q;
target_ulong handler;
int sig;
if (!signal_pending)
return;
k = sigact_table;
for(sig = 1; sig <= NSIG; sig++) {
if (k->pending)
goto handle_signal;
k++;
}
/* if no signal is pending, just return */
signal_pending = 0;
return;
handle_signal:
#ifdef DEBUG_SIGNAL
fprintf(stderr, "qemu: process signal %d\n", sig);
#endif
/* dequeue signal */
q = k->first;
k->first = q->next;
if (!k->first)
k->pending = 0;
sig = gdb_handlesig (cpu_env, sig);
if (!sig) {
fprintf (stderr, "Lost signal\n");
abort();
}
handler = k->sa.sa_handler;
if (handler == SIG_DFL) {
/* default handler : ignore some signal. The other are fatal */
if (sig != SIGCHLD &&
sig != SIGURG &&
sig != SIGWINCH) {
force_sig(sig);
}
} else if (handler == SIG_IGN) {
/* ignore sig */
} else if (handler == SIG_ERR) {
force_sig(sig);
} else {
setup_frame(sig, k, 0, cpu_env);
if (k->sa.sa_flags & SA_RESETHAND)
k->sa.sa_handler = SIG_DFL;
}
if (q != &k->info)
free_sigqueue(q);
}

File diff suppressed because it is too large Load diff

View file

@ -1,384 +0,0 @@
/* generated from xnu/bsd/kern/syscalls.master */
ENTRY("syscall", SYS_syscall, do_unix_syscall_indirect, 0, CALL_INDIRECT, VOID) /* 0 indirect syscall */
ENTRY("exit", SYS_exit, do_exit, 1, CALL_DIRECT, INT) /* 1 */
ENTRY("fork", SYS_fork, fork, 0, CALL_NOERRNO, VOID) /* 2 */
ENTRY("read", SYS_read, do_read, 3, CALL_DIRECT, INT, PTR, SIZE) /* 3 */
ENTRY("write", SYS_write, write, 3, CALL_DIRECT, INT, PTR, SIZE) /* 4 */
ENTRY("open", SYS_open, do_open, 3, CALL_DIRECT, PTR, INT, INT) /* 5 */
ENTRY("close", SYS_close, close, 1, CALL_DIRECT, INT) /* 6 */
ENTRY("wait4", SYS_wait4, wait4, 4, CALL_DIRECT, INT, PTR, INT, PTR) /* 7 */
ENTRY("", 8, no_syscall, 0, CALL_INDIRECT, VOID) /* 8 old creat */
ENTRY("link", SYS_link, link, 2, CALL_DIRECT, PTR, PTR) /* 9 */
ENTRY("unlink", SYS_unlink, unlink, 1, CALL_DIRECT, PTR) /* 10 */
ENTRY("", 11, no_syscall, 0, CALL_INDIRECT, VOID) /* 11 old execv */
ENTRY("chdir", SYS_chdir, chdir, 1, CALL_DIRECT, PTR) /* 12 */
ENTRY("fchdir", SYS_fchdir, fchdir, 1, CALL_DIRECT, INT) /* 13 */
ENTRY("mknod", SYS_mknod, mknod, 3, CALL_DIRECT, PTR, INT, INT) /* 14 */
ENTRY("chmod", SYS_chmod, chmod, 2, CALL_DIRECT, PTR, INT) /* 15 */
ENTRY("chown", SYS_chown, chown, 3, CALL_DIRECT, PTR, INT, INT) /* 16 */
ENTRY("obreak", SYS_obreak, no_syscall, 1, CALL_INDIRECT, VOID) /* 17 old break */
ENTRY("ogetfsstat", 18, unimpl_unix_syscall, 3, CALL_INDIRECT, PTR, INT, INT) /* 18 */
ENTRY("", 19, no_syscall, 0, CALL_INDIRECT, VOID) /* 19 old lseek */
ENTRY("getpid", SYS_getpid, getpid, 0, CALL_NOERRNO, VOID) /* 20 */
ENTRY("", 21, no_syscall, 0, CALL_INDIRECT, VOID) /* 21 old mount */
ENTRY("", 22, no_syscall, 0, CALL_INDIRECT, VOID) /* 22 old umount */
ENTRY("setuid", SYS_setuid, setuid, 1, CALL_DIRECT, INT) /* 23 */
ENTRY("getuid", SYS_getuid, getuid, 0, CALL_NOERRNO, VOID) /* 24 */
ENTRY("geteuid", SYS_geteuid, geteuid, 0, CALL_NOERRNO, VOID) /* 25 */
ENTRY("ptrace", SYS_ptrace, ptrace, 4, CALL_DIRECT, INT, INT, PTR, INT) /* 26 */
ENTRY("recvmsg", SYS_recvmsg, recvmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 27 */
ENTRY("sendmsg", SYS_sendmsg, sendmsg, 3, CALL_DIRECT, INT, PTR, INT) /* 28 */
ENTRY("recvfrom", SYS_recvfrom, recvfrom, 6, CALL_DIRECT, INT, PTR, INT, INT, PTR, PTR) /* 29 */
ENTRY("accept", SYS_accept, accept, 3, CALL_DIRECT, INT, PTR, PTR) /* 30 */
ENTRY("getpeername", SYS_getpeername, getpeername, 3, CALL_DIRECT, INT, PTR, PTR) /* 31 */
ENTRY("getsockname", SYS_getsockname, getsockname, 3, CALL_DIRECT, INT, PTR, PTR) /* 32 */
ENTRY("access", SYS_access, access, 2, CALL_DIRECT, PTR, INT) /* 33 */
ENTRY("chflags", SYS_chflags, chflags, 2, CALL_DIRECT, PTR, INT) /* 34 */
ENTRY("fchflags", SYS_fchflags, fchflags, 2, CALL_DIRECT, INT, INT) /* 35 */
ENTRY("sync", SYS_sync, do_sync, 0, CALL_INDIRECT, VOID) /* 36 */
ENTRY("kill", SYS_kill, kill, 2, CALL_DIRECT, INT, INT) /* 37 */
ENTRY("", 38, no_syscall, 0, CALL_INDIRECT, VOID) /* 38 old stat */
ENTRY("getppid", SYS_getppid, getppid, 0, CALL_DIRECT, VOID) /* 39 */
ENTRY("", 40, no_syscall, 0, CALL_INDIRECT, VOID) /* 40 old lstat */
ENTRY("dup", SYS_dup, dup, 1, CALL_DIRECT, INT) /* 41 */
ENTRY("pipe", SYS_pipe, pipe, 0, CALL_INDIRECT, PTR) /* 42 */
ENTRY("getegid", SYS_getegid, getegid, 0, CALL_NOERRNO, VOID) /* 43 */
ENTRY("profil", SYS_profil, profil, 4, CALL_DIRECT, PTR, SIZE, INT, INT) /* 44 */
ENTRY("ktrace", SYS_ktrace, no_syscall, 4, CALL_INDIRECT, VOID) /* 45 */
ENTRY("sigaction", SYS_sigaction, do_sigaction, 3, CALL_DIRECT, INT, PTR, PTR) /* 46 */
ENTRY("getgid", SYS_getgid, getgid, 0, CALL_NOERRNO, VOID) /* 47 */
ENTRY("sigprocmask", SYS_sigprocmask, do_sigprocmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 48 */
ENTRY("getlogin", SYS_getlogin, do_getlogin, 2, CALL_DIRECT, PTR, UINT) /* 49 XXX */
ENTRY("setlogin", SYS_setlogin, setlogin, 1, CALL_DIRECT, PTR) /* 50 */
ENTRY("acct", SYS_acct, acct, 1, CALL_DIRECT, PTR) /* 51 */
ENTRY("sigpending", SYS_sigpending, sigpending, 1, CALL_DIRECT, PTR) /* 52 */
ENTRY("sigaltstack", SYS_sigaltstack, do_sigaltstack, 2, CALL_DIRECT, PTR, PTR) /* 53 */
ENTRY("ioctl", SYS_ioctl, do_ioctl, 3, CALL_DIRECT, INT, INT, INT) /* 54 */
ENTRY("reboot", SYS_reboot, unimpl_unix_syscall, 2, CALL_INDIRECT, INT, PTR) /* 55 */
ENTRY("revoke", SYS_revoke, revoke, 1, CALL_DIRECT, PTR) /* 56 */
ENTRY("symlink", SYS_symlink, symlink, 2, CALL_DIRECT, PTR, PTR) /* 57 */
ENTRY("readlink", SYS_readlink, readlink, 3, CALL_DIRECT, PTR, PTR, INT) /* 58 */
ENTRY("execve", SYS_execve, do_execve, 3, CALL_DIRECT, PTR, PTR, PTR) /* 59 */
ENTRY("umask", SYS_umask, umask, 1, CALL_DIRECT, INT) /* 60 */
ENTRY("chroot", SYS_chroot, chroot, 1, CALL_DIRECT, PTR) /* 61 */
ENTRY("", 62, no_syscall, 0, CALL_INDIRECT, VOID) /* 62 old fstat */
ENTRY("", 63, no_syscall, 0, CALL_INDIRECT, VOID) /* 63 used internally , reserved */
ENTRY("", 64, no_syscall, 0, CALL_INDIRECT, VOID) /* 64 old getpagesize */
ENTRY("msync", SYS_msync, target_msync, 3, CALL_DIRECT, UINT /*PTR*/, SIZE, INT) /* 65 */
ENTRY("vfork", SYS_vfork, vfork, 0, CALL_DIRECT, VOID) /* 66 */
ENTRY("", 67, no_syscall, 0, CALL_INDIRECT, VOID) /* 67 old vread */
ENTRY("", 68, no_syscall, 0, CALL_INDIRECT, VOID) /* 68 old vwrite */
ENTRY("sbrk", SYS_sbrk, sbrk, 1, CALL_DIRECT, INT) /* 69 */
ENTRY("sstk", SYS_sstk, no_syscall, 1, CALL_INDIRECT, VOID) /* 70 */
ENTRY("", 71, no_syscall, 0, CALL_INDIRECT, VOID) /* 71 old mmap */
ENTRY("ovadvise", SYS_ovadvise, no_syscall, 0, CALL_INDIRECT, VOID) /* 72 old vadvise */
ENTRY("munmap", SYS_munmap, target_munmap, 2, CALL_DIRECT, UINT /* PTR */, SIZE) /* 73 */
ENTRY("mprotect", SYS_mprotect, mprotect, 3, CALL_DIRECT, PTR, SIZE, INT) /* 74 */
ENTRY("madvise", SYS_madvise, madvise, 3, CALL_DIRECT, PTR, SIZE, INT) /* 75 */
ENTRY("", 76, no_syscall, 0, CALL_INDIRECT, VOID) /* 76 old vhangup */
ENTRY("", 77, no_syscall, 0, CALL_INDIRECT, VOID) /* 77 old vlimit */
ENTRY("mincore", SYS_mincore, mincore, 3, CALL_DIRECT, PTR, SIZE, PTR) /* 78 */
ENTRY("getgroups", SYS_getgroups, do_getgroups, 2, CALL_DIRECT, UINT, PTR) /* 79 */
ENTRY("setgroups", SYS_setgroups, setgroups, 2, CALL_DIRECT, UINT, PTR) /* 80 */
ENTRY("getpgrp", SYS_getpgrp, getpgrp, 0, CALL_DIRECT, VOID) /* 81 */
ENTRY("setpgid", SYS_setpgid, setpgid, 2, CALL_DIRECT, INT, INT) /* 82 */
ENTRY("setitimer", SYS_setitimer, setitimer, 3, CALL_DIRECT, INT, PTR, PTR) /* 83 */
ENTRY("", 84, no_syscall, 0, CALL_INDIRECT, VOID) /* 84 old wait */
ENTRY("swapon", SYS_swapon, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 85 */
ENTRY("getitimer", SYS_getitimer, getitimer, 2, CALL_DIRECT, INT, PTR) /* 86 */
ENTRY("", 87, no_syscall, 0, CALL_INDIRECT, VOID) /* 87 old gethostname */
ENTRY("", 88, no_syscall, 0, CALL_INDIRECT, VOID) /* 88 old sethostname */
ENTRY("getdtablesize", SYS_getdtablesize, getdtablesize, 0, CALL_DIRECT, VOID) /* 89 */
ENTRY("dup2", SYS_dup2, dup2, 2, CALL_DIRECT, INT, INT) /* 90 */
ENTRY("", 91, no_syscall, 0, CALL_INDIRECT, VOID) /* 91 old getdopt */
ENTRY("fcntl", SYS_fcntl, do_fcntl, 3, CALL_DIRECT, INT, INT, INT) /* 92 */
ENTRY("select", SYS_select, select, 5, CALL_DIRECT, INT, PTR, PTR, PTR, PTR) /* 93 */
ENTRY("", 94, no_syscall, 0, CALL_INDIRECT, VOID) /* 94 old setdopt */
ENTRY("fsync", SYS_fsync, fsync, 1, CALL_DIRECT, INT) /* 95 */
ENTRY("setpriority", SYS_setpriority, setpriority, 3, CALL_DIRECT, INT, INT, INT) /* 96 */
ENTRY("socket", SYS_socket, socket, 3, CALL_DIRECT, INT, INT, INT) /* 97 */
ENTRY("connect", SYS_connect, connect, 3, CALL_DIRECT, INT, PTR, INT) /* 98 */
ENTRY("", 99, no_syscall, 0, CALL_INDIRECT, VOID) /* 99 old accept */
ENTRY("getpriority", SYS_getpriority, getpriority, 2, CALL_DIRECT, INT, INT) /* 100 */
ENTRY("", 101, no_syscall, 0, CALL_INDIRECT, VOID) /* 101 old send */
ENTRY("", 102, no_syscall, 0, CALL_INDIRECT, VOID) /* 102 old recv */
ENTRY("", 103, no_syscall, 0, CALL_INDIRECT, VOID) /* 103 old sigreturn */
ENTRY("bind", SYS_bind, bind, 3, CALL_DIRECT, INT, PTR, INT) /* 104 */
ENTRY("setsockopt", SYS_setsockopt, setsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, INT) /* 105 */
ENTRY("listen", SYS_listen, listen, 2, CALL_DIRECT, INT, INT) /* 106 */
ENTRY("", 107, no_syscall, 0, CALL_INDIRECT, VOID) /* 107 old vtimes */
ENTRY("", 108, no_syscall, 0, CALL_INDIRECT, VOID) /* 108 old sigvec */
ENTRY("", 109, no_syscall, 0, CALL_INDIRECT, VOID) /* 109 old sigblock */
ENTRY("", 110, no_syscall, 0, CALL_INDIRECT, VOID) /* 110 old sigsetmask */
ENTRY("sigsuspend", SYS_sigsuspend, unimpl_unix_syscall, 1, CALL_INDIRECT, INT) /* 111 */
ENTRY("", 112, no_syscall, 0, CALL_INDIRECT, VOID) /* 112 old sigstack */
ENTRY("", 113, no_syscall, 0, CALL_INDIRECT, VOID) /* 113 old recvmsg */
ENTRY("", 114, no_syscall, 0, CALL_INDIRECT, VOID) /* 114 old sendmsg */
ENTRY("", 115, no_syscall, 0, CALL_INDIRECT, VOID) /* 115 old vtrace */
ENTRY("gettimeofday", SYS_gettimeofday, do_gettimeofday, 2, CALL_DIRECT, PTR, PTR) /* 116 */
ENTRY("getrusage", SYS_getrusage, getrusage, 2, CALL_DIRECT, INT, PTR) /* 117 */
ENTRY("getsockopt", SYS_getsockopt, getsockopt, 5, CALL_DIRECT, INT, INT, INT, PTR, PTR) /* 118 */
ENTRY("", 119, no_syscall, 0, CALL_INDIRECT, VOID) /* 119 old resuba */
ENTRY("readv", SYS_readv, do_readv, 3, CALL_DIRECT, INT, PTR, UINT) /* 120 */
ENTRY("writev", SYS_writev, do_writev, 3, CALL_DIRECT, INT, PTR, UINT) /* 121 */
ENTRY("settimeofday", SYS_settimeofday, settimeofday, 2, CALL_DIRECT, PTR, PTR) /* 122 */
ENTRY("fchown", SYS_fchown, fchown, 3, CALL_DIRECT, INT, INT, INT) /* 123 */
ENTRY("fchmod", SYS_fchmod, fchmod, 2, CALL_DIRECT, INT, INT) /* 124 */
ENTRY("", 125, no_syscall, 0, CALL_INDIRECT, VOID) /* 125 old recvfrom */
ENTRY("", 126, no_syscall, 0, CALL_INDIRECT, VOID) /* 126 old setreuid */
ENTRY("", 127, no_syscall, 0, CALL_INDIRECT, VOID) /* 127 old setregid */
ENTRY("rename", SYS_rename, rename, 2, CALL_DIRECT, PTR, PTR) /* 128 */
ENTRY("", 129, no_syscall, 0, CALL_INDIRECT, VOID) /* 129 old truncate */
ENTRY("", 130, no_syscall, 0, CALL_INDIRECT, VOID) /* 130 old ftruncate */
ENTRY("flock", SYS_flock, flock, 2, CALL_DIRECT, INT, INT) /* 131 */
ENTRY("mkfifo", SYS_mkfifo, mkfifo, 2, CALL_DIRECT, PTR, INT) /* 132 */
ENTRY("sendto", SYS_sendto, sendto, 6, CALL_DIRECT, INT, PTR, SIZE, INT, PTR, INT) /* 133 */
ENTRY("shutdown", SYS_shutdown, shutdown, 2, CALL_DIRECT, INT, INT) /* 134 */
ENTRY("socketpair", SYS_socketpair, socketpair, 4, CALL_DIRECT, INT, INT, INT, PTR) /* 135 */
ENTRY("mkdir", SYS_mkdir, mkdir, 2, CALL_DIRECT, PTR, INT) /* 136 */
ENTRY("rmdir", SYS_rmdir, rmdir, 1, CALL_DIRECT, PTR) /* 137 */
ENTRY("utimes", SYS_utimes, do_utimes, 2, CALL_DIRECT, PTR, PTR) /* 138 */
ENTRY("futimes", SYS_futimes, do_futimes, 2, CALL_DIRECT, INT, PTR) /* 139 */
ENTRY("adjtime", SYS_adjtime, adjtime, 2, CALL_DIRECT, PTR, PTR) /* 140 */
ENTRY("", 141, no_syscall, 0, CALL_INDIRECT, VOID) /* 141 old getpeername */
ENTRY("", 142, no_syscall, 0, CALL_INDIRECT, VOID) /* 142 old gethostid */
ENTRY("", 143, no_syscall, 0, CALL_INDIRECT, VOID) /* 143 old sethostid */
ENTRY("", 144, no_syscall, 0, CALL_INDIRECT, VOID) /* 144 old getrlimit */
ENTRY("", 145, no_syscall, 0, CALL_INDIRECT, VOID) /* 145 old setrlimit */
ENTRY("", 146, no_syscall, 0, CALL_INDIRECT, VOID) /* 146 old killpg */
ENTRY("setsid", SYS_setsid, setsid, 0, CALL_DIRECT, VOID) /* 147 */
ENTRY("", 148, no_syscall, 0, CALL_INDIRECT, VOID) /* 148 old setquota */
ENTRY("", 149, no_syscall, 0, CALL_INDIRECT, VOID) /* 149 old qquota */
ENTRY("", 150, no_syscall, 0, CALL_INDIRECT, VOID) /* 150 old getsockname */
ENTRY("getpgid", SYS_getpgid, getpgid, 1, CALL_DIRECT, INT) /* 151 */
ENTRY("setprivexec", SYS_setprivexec, no_syscall, 1, CALL_INDIRECT, VOID) /* 152 */
ENTRY("pread", SYS_pread, do_pread, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 153 */
ENTRY("pwrite", SYS_pwrite, pwrite, 4, CALL_DIRECT, INT, PTR, SIZE, OFFSET) /* 154 */
#ifdef SYS_nfssvc
ENTRY("nfssvc", SYS_nfssvc, nfssvc, 2, CALL_DIRECT, INT, PTR) /* 155 */
#else
ENTRY("nfssvc", 155, no_syscall, 2, CALL_INDIRECT, VOID) /* 155 */
#endif
ENTRY("", 155, no_syscall, 0, CALL_INDIRECT, VOID) /* 155 */
ENTRY("", 156, no_syscall, 0, CALL_INDIRECT, VOID) /* 156 old getdirentries */
ENTRY("statfs", SYS_statfs, do_statfs, 2, CALL_DIRECT, PTR, PTR) /* 157 */
ENTRY("fstatfs", SYS_fstatfs, do_fstatfs, 2, CALL_DIRECT, INT, PTR) /* 158 */
ENTRY("unmount", SYS_unmount, unmount, 2, CALL_DIRECT, PTR, INT) /* 159 */
ENTRY("", 160, no_syscall, 0, CALL_INDIRECT, VOID) /* 160 old async_daemon */
ENTRY("", 161, no_syscall, 0, CALL_INDIRECT, VOID) /* 161 */
ENTRY("", 162, no_syscall, 0, CALL_INDIRECT, VOID) /* 162 old getdomainname */
ENTRY("", 163, no_syscall, 0, CALL_INDIRECT, VOID) /* 163 old setdomainname */
ENTRY("", 164, no_syscall, 0, CALL_INDIRECT, VOID) /* 164 */
ENTRY("quotactl", SYS_quotactl, no_syscall, 4, CALL_INDIRECT, VOID) /* 165 */
ENTRY("", 166, no_syscall, 0, CALL_INDIRECT, VOID) /* 166 old exportfs */
ENTRY("mount", SYS_mount, mount, 4, CALL_DIRECT, PTR, PTR, INT, PTR) /* 167 */
ENTRY("", 168, no_syscall, 0, CALL_INDIRECT, VOID) /* 168 old ustat */
ENTRY("", 169, no_syscall, 0, CALL_INDIRECT, VOID) /* 169 */
ENTRY("table", SYS_table, no_syscall, 0, CALL_INDIRECT, VOID) /* 170 old table */
ENTRY("", 171, no_syscall, 0, CALL_INDIRECT, VOID) /* 171 old wait3 */
ENTRY("", 172, no_syscall, 0, CALL_INDIRECT, VOID) /* 172 old rpause */
ENTRY("waitid", SYS_waitid, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 173 */
ENTRY("", 174, no_syscall, 0, CALL_INDIRECT, VOID) /* 174 old getdents */
ENTRY("", 175, no_syscall, 0, CALL_INDIRECT, VOID) /* 175 old gc_control */
ENTRY("add_profil", SYS_add_profil, add_profil, 4, CALL_DIRECT, PTR, SIZE, UINT, UINT) /* 176 */
ENTRY("", 177, no_syscall, 0, CALL_INDIRECT, VOID) /* 177 */
ENTRY("", 178, no_syscall, 0, CALL_INDIRECT, VOID) /* 178 */
ENTRY("", 179, no_syscall, 0, CALL_INDIRECT, VOID) /* 179 */
ENTRY("kdebug_trace", SYS_kdebug_trace, no_syscall, 6, CALL_INDIRECT, VOID) /* 180 */
ENTRY("setgid", SYS_setgid, setgid, 1, CALL_DIRECT, INT) /* 181 */
ENTRY("setegid", SYS_setegid, setegid, 1, CALL_DIRECT, INT) /* 182 */
ENTRY("seteuid", SYS_seteuid, seteuid, 1, CALL_DIRECT, INT) /* 183 */
ENTRY("sigreturn", SYS_sigreturn, do_sigreturn, 2, CALL_INDIRECT, PTR, INT) /* 184 */
ENTRY("chud", SYS_chud, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 185 */
ENTRY("", 186, no_syscall, 0, CALL_INDIRECT, VOID) /* 186 */
ENTRY("", 187, no_syscall, 0, CALL_INDIRECT, VOID) /* 187 */
ENTRY("stat", SYS_stat, do_stat, 2, CALL_DIRECT, PTR, PTR) /* 188 */
ENTRY("fstat", SYS_fstat, do_fstat, 2, CALL_DIRECT, INT, PTR) /* 189 */
ENTRY("lstat", SYS_lstat, do_lstat, 2, CALL_DIRECT, PTR, PTR) /* 190 */
ENTRY("pathconf", SYS_pathconf, pathconf, 2, CALL_DIRECT, PTR, INT) /* 191 */
ENTRY("fpathconf", SYS_fpathconf, fpathconf, 2, CALL_DIRECT, INT, INT) /* 192 */
ENTRY("getfsstat", SYS_getfsstat, do_getfsstat, 3, CALL_DIRECT, PTR, INT, INT) /* 193 */
ENTRY("", 193, no_syscall, 0, CALL_INDIRECT, VOID) /* 193 */
ENTRY("getrlimit", SYS_getrlimit, getrlimit, 2, CALL_DIRECT, UINT, PTR) /* 194 */
ENTRY("setrlimit", SYS_setrlimit, setrlimit, 2, CALL_DIRECT, UINT, PTR) /* 195 */
ENTRY("getdirentries", SYS_getdirentries, do_getdirentries, 4, CALL_DIRECT, INT, PTR, UINT, PTR) /* 196 */
ENTRY("mmap", SYS_mmap, target_mmap, 6, CALL_DIRECT, UINT /*PTR*/, SIZE, INT, INT, INT, OFFSET) /* 197 */
ENTRY("", 198, no_syscall, 0, CALL_INDIRECT, VOID) /* 198 __syscall */
ENTRY("lseek", SYS_lseek, do_lseek, 3, CALL_INDIRECT, INT, OFFSET, INT) /* 199 */
ENTRY("truncate", SYS_truncate, truncate, 2, CALL_DIRECT, PTR, OFFSET) /* 200 */
ENTRY("ftruncate", SYS_ftruncate, ftruncate, 2, CALL_DIRECT, INT, OFFSET) /* 201 */
ENTRY("__sysctl", SYS___sysctl, do___sysctl, 6, CALL_DIRECT, PTR, INT, PTR, PTR, PTR, SIZE) /* 202 */
ENTRY("mlock", SYS_mlock, mlock, 2, CALL_DIRECT, PTR, SIZE) /* 203 */
ENTRY("munlock", SYS_munlock, munlock, 2, CALL_DIRECT, PTR, SIZE) /* 204 */
ENTRY("undelete", SYS_undelete, undelete, 1, CALL_DIRECT, PTR) /* 205 */
ENTRY("ATsocket", SYS_ATsocket, no_syscall, 1, CALL_INDIRECT, VOID) /* 206 */
ENTRY("ATgetmsg", SYS_ATgetmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 207 */
ENTRY("ATputmsg", SYS_ATputmsg, no_syscall, 4, CALL_INDIRECT, VOID) /* 208 */
ENTRY("ATPsndreq", SYS_ATPsndreq, no_syscall, 4, CALL_INDIRECT, VOID) /* 209 */
ENTRY("ATPsndrsp", SYS_ATPsndrsp, no_syscall, 4, CALL_INDIRECT, VOID) /* 210 */
ENTRY("ATPgetreq", SYS_ATPgetreq, no_syscall, 3, CALL_INDIRECT, VOID) /* 211 */
ENTRY("ATPgetrsp", SYS_ATPgetrsp, no_syscall, 2, CALL_INDIRECT, VOID) /* 212 */
ENTRY("", 213, no_syscall, 0, CALL_INDIRECT, VOID) /* 213 Reserved for AppleTalk */
ENTRY("kqueue_from_portset_np", SYS_kqueue_from_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 214 */
ENTRY("kqueue_portset_np", SYS_kqueue_portset_np, no_syscall, 1, CALL_INDIRECT, VOID) /* 215 */
ENTRY("mkcomplex", SYS_mkcomplex, no_syscall, 3, CALL_INDIRECT, VOID) /* 216 soon to be obsolete */
ENTRY("statv", SYS_statv, no_syscall, 2, CALL_INDIRECT, VOID) /* 217 soon to be obsolete */
ENTRY("lstatv", SYS_lstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 218 soon to be obsolete */
ENTRY("fstatv", SYS_fstatv, no_syscall, 2, CALL_INDIRECT, VOID) /* 219 soon to be obsolete */
ENTRY("getattrlist", SYS_getattrlist, do_getattrlist, 5, CALL_DIRECT, PTR, PTR, PTR, SIZE, UINT) /* 220 */
ENTRY("setattrlist", SYS_setattrlist, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 221 */
ENTRY("getdirentriesattr", SYS_getdirentriesattr, do_getdirentriesattr, 8, CALL_DIRECT, INT, PTR, PTR, SIZE, PTR, PTR, PTR, UINT) /* 222 */
ENTRY("exchangedata", SYS_exchangedata, exchangedata, 3, CALL_DIRECT, PTR, PTR, UINT) /* 223 */
ENTRY("checkuseraccess", SYS_checkuseraccess, checkuseraccess, 6, CALL_DIRECT, PTR, INT, PTR, INT, INT, UINT) /* 224 */
ENTRY("", 224, no_syscall, 0, CALL_INDIRECT, VOID) /* 224 HFS checkuseraccess check access to a file */
ENTRY("searchfs", SYS_searchfs, searchfs, 6, CALL_DIRECT, PTR, PTR, PTR, UINT, UINT, PTR) /* 225 */
ENTRY("delete", SYS_delete, no_syscall, 1, CALL_INDIRECT, VOID) /* 226 private delete ( Carbon semantics ) */
ENTRY("copyfile", SYS_copyfile, no_syscall, 4, CALL_INDIRECT, VOID) /* 227 */
ENTRY("", 228, no_syscall, 0, CALL_INDIRECT, VOID) /* 228 */
ENTRY("", 229, no_syscall, 0, CALL_INDIRECT, VOID) /* 229 */
ENTRY("poll", SYS_poll, no_syscall, 3, CALL_INDIRECT, VOID) /* 230 */
ENTRY("watchevent", SYS_watchevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 231 */
ENTRY("waitevent", SYS_waitevent, no_syscall, 2, CALL_INDIRECT, VOID) /* 232 */
ENTRY("modwatch", SYS_modwatch, no_syscall, 2, CALL_INDIRECT, VOID) /* 233 */
ENTRY("getxattr", SYS_getxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 234 */
ENTRY("fgetxattr", SYS_fgetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 235 */
ENTRY("setxattr", SYS_setxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 236 */
ENTRY("fsetxattr", SYS_fsetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 237 */
ENTRY("removexattr", SYS_removexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 238 */
ENTRY("fremovexattr", SYS_fremovexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 239 */
ENTRY("listxattr", SYS_listxattr, listxattr, 4, CALL_INDIRECT, VOID) /* 240 */
ENTRY("flistxattr", SYS_flistxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 241 */
ENTRY("fsctl", SYS_fsctl, fsctl, 4, CALL_DIRECT, PTR, UINT, PTR, UINT) /* 242 */
ENTRY("initgroups", SYS_initgroups, unimpl_unix_syscall, 3, CALL_INDIRECT, UINT, PTR, INT) /* 243 */
ENTRY("", 244, no_syscall, 0, CALL_INDIRECT, VOID) /* 244 */
ENTRY("", 245, no_syscall, 0, CALL_INDIRECT, VOID) /* 245 */
ENTRY("", 246, no_syscall, 0, CALL_INDIRECT, VOID) /* 246 */
#ifdef SYS_nfsclnt
ENTRY("nfsclnt", SYS_nfsclnt, nfsclnt, 2, CALL_DIRECT, INT, PTR) /* 247 */
#else
ENTRY("nfsclnt", 247, no_syscall, 2, CALL_INDIRECT, VOID) /* 247 */
#endif
ENTRY("", 247, no_syscall, 0, CALL_INDIRECT, VOID) /* 247 */
ENTRY("", 248, no_syscall, 0, CALL_INDIRECT, VOID) /* 248 */
ENTRY("", 249, no_syscall, 0, CALL_INDIRECT, VOID) /* 249 */
ENTRY("minherit", SYS_minherit, minherit, 3, CALL_DIRECT, PTR, INT, INT) /* 250 */
ENTRY("semsys", SYS_semsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 251 */
ENTRY("msgsys", SYS_msgsys, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 252 */
ENTRY("shmsys", SYS_shmsys, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 253 */
ENTRY("semctl", SYS_semctl, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 254 */
ENTRY("semget", SYS_semget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 255 */
ENTRY("semop", SYS_semop, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 256 */
ENTRY("", 257, no_syscall, 0, CALL_INDIRECT, VOID) /* 257 */
ENTRY("msgctl", SYS_msgctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 258 */
ENTRY("msgget", SYS_msgget, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 259 */
ENTRY("msgsnd", SYS_msgsnd, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 260 */
ENTRY("msgrcv", SYS_msgrcv, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 261 */
ENTRY("shmat", SYS_shmat, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 262 */
ENTRY("shmctl", SYS_shmctl, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 263 */
ENTRY("shmdt", SYS_shmdt, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 264 */
ENTRY("shmget", SYS_shmget, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 265 */
ENTRY("shm_open", SYS_shm_open, shm_open, 3, CALL_DIRECT, PTR, INT, INT) /* 266 */
ENTRY("shm_unlink", SYS_shm_unlink, shm_unlink, 1, CALL_DIRECT, PTR) /* 267 */
ENTRY("sem_open", SYS_sem_open, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 268 */
ENTRY("sem_close", SYS_sem_close, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 269 */
ENTRY("sem_unlink", SYS_sem_unlink, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 270 */
ENTRY("sem_wait", SYS_sem_wait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 271 */
ENTRY("sem_trywait", SYS_sem_trywait, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 272 */
ENTRY("sem_post", SYS_sem_post, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 273 */
ENTRY("sem_getvalue", SYS_sem_getvalue, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 274 */
ENTRY("sem_init", SYS_sem_init, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 275 */
ENTRY("sem_destroy", SYS_sem_destroy, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 276 */
ENTRY("open_extended", SYS_open_extended, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 277 */
ENTRY("umask_extended", SYS_umask_extended, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 278 */
ENTRY("stat_extended", SYS_stat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 279 */
ENTRY("lstat_extended", SYS_lstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 280 */
ENTRY("fstat_extended", SYS_fstat_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 281 */
ENTRY("chmod_extended", SYS_chmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 282 */
ENTRY("fchmod_extended", SYS_fchmod_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 283 */
ENTRY("access_extended", SYS_access_extended, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 284 */
ENTRY("settid", SYS_settid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 285 */
ENTRY("gettid", SYS_gettid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 286 */
ENTRY("setsgroups", SYS_setsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 287 */
ENTRY("getsgroups", SYS_getsgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 288 */
ENTRY("setwgroups", SYS_setwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 289 */
ENTRY("getwgroups", SYS_getwgroups, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 290 */
ENTRY("mkfifo_extended", SYS_mkfifo_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 291 */
ENTRY("mkdir_extended", SYS_mkdir_extended, unimpl_unix_syscall, 5, CALL_INDIRECT, VOID) /* 292 */
ENTRY("identitysvc", SYS_identitysvc, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 293 */
ENTRY("", 294, no_syscall, 0, CALL_INDIRECT, VOID) /* 294 */
ENTRY("", 295, no_syscall, 0, CALL_INDIRECT, VOID) /* 295 */
ENTRY("load_shared_file", SYS_load_shared_file, unimpl_unix_syscall, 7, CALL_INDIRECT, VOID) /* 296 */
ENTRY("reset_shared_file", SYS_reset_shared_file, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 297 */
ENTRY("new_system_shared_regions", SYS_new_system_shared_regions, unimpl_unix_syscall, 0, CALL_INDIRECT, VOID) /* 298 */
ENTRY("shared_region_map_file_np", SYS_shared_region_map_file_np, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 299 */
ENTRY("shared_region_make_private_np", SYS_shared_region_make_private_np, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 300 */
ENTRY("", 301, no_syscall, 0, CALL_INDIRECT, VOID) /* 301 */
ENTRY("", 302, no_syscall, 0, CALL_INDIRECT, VOID) /* 302 */
ENTRY("", 303, no_syscall, 0, CALL_INDIRECT, VOID) /* 303 */
ENTRY("", 304, no_syscall, 0, CALL_INDIRECT, VOID) /* 304 */
ENTRY("", 305, no_syscall, 0, CALL_INDIRECT, VOID) /* 305 */
ENTRY("", 306, no_syscall, 0, CALL_INDIRECT, VOID) /* 306 */
ENTRY("", 307, no_syscall, 0, CALL_INDIRECT, VOID) /* 307 */
ENTRY("", 308, no_syscall, 0, CALL_INDIRECT, VOID) /* 308 */
ENTRY("", 309, no_syscall, 0, CALL_INDIRECT, VOID) /* 309 */
ENTRY("getsid", SYS_getsid, getsid, 1, CALL_DIRECT, INT) /* 310 */
ENTRY("settid_with_pid", SYS_settid_with_pid, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 311 */
ENTRY("", 312, no_syscall, 0, CALL_INDIRECT, VOID) /* 312 */
ENTRY("aio_fsync", SYS_aio_fsync, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 313 */
ENTRY("aio_return", SYS_aio_return, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 314 */
ENTRY("aio_suspend", SYS_aio_suspend, unimpl_unix_syscall, 3, CALL_INDIRECT, VOID) /* 315 */
ENTRY("aio_cancel", SYS_aio_cancel, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 316 */
ENTRY("aio_error", SYS_aio_error, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 317 */
ENTRY("aio_read", SYS_aio_read, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 318 */
ENTRY("aio_write", SYS_aio_write, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 319 */
ENTRY("lio_listio", SYS_lio_listio, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 320 */
ENTRY("", 321, no_syscall, 0, CALL_INDIRECT, VOID) /* 321 */
ENTRY("", 322, no_syscall, 0, CALL_INDIRECT, VOID) /* 322 */
ENTRY("", 323, no_syscall, 0, CALL_INDIRECT, VOID) /* 323 */
ENTRY("mlockall", SYS_mlockall, mlockall, 1, CALL_DIRECT, INT) /* 324 */
ENTRY("munlockall", SYS_munlockall, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 325 */
ENTRY("", 326, no_syscall, 0, CALL_INDIRECT, VOID) /* 326 */
ENTRY("issetugid", SYS_issetugid, issetugid, 0, CALL_DIRECT, VOID) /* 327 */
ENTRY("__pthread_kill", SYS___pthread_kill, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 328 */
ENTRY("pthread_sigmask", SYS_pthread_sigmask, pthread_sigmask, 3, CALL_DIRECT, INT, PTR, PTR) /* 329 */
ENTRY("sigwait", SYS_sigwait, sigwait, 2, CALL_DIRECT, PTR, PTR) /* 330 */
ENTRY("__disable_threadsignal", SYS___disable_threadsignal, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 331 */
ENTRY("__pthread_markcancel", SYS___pthread_markcancel, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 332 */
ENTRY("__pthread_canceled", SYS___pthread_canceled, unimpl_unix_syscall, 1, CALL_INDIRECT, VOID) /* 333 */
ENTRY("__semwait_signal", SYS___semwait_signal, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 334 */
ENTRY("utrace", SYS_utrace, unimpl_unix_syscall, 2, CALL_INDIRECT, VOID) /* 335 */
ENTRY("proc_info", SYS_proc_info, unimpl_unix_syscall, 6, CALL_INDIRECT, VOID) /* 336 */
ENTRY("", 337, no_syscall, 0, CALL_INDIRECT, VOID) /* 337 */
ENTRY("", 338, no_syscall, 0, CALL_INDIRECT, VOID) /* 338 */
ENTRY("", 339, no_syscall, 0, CALL_INDIRECT, VOID) /* 339 */
ENTRY("", 340, no_syscall, 0, CALL_INDIRECT, VOID) /* 340 */
ENTRY("", 341, no_syscall, 0, CALL_INDIRECT, VOID) /* 341 */
ENTRY("", 342, no_syscall, 0, CALL_INDIRECT, VOID) /* 342 */
ENTRY("", 343, no_syscall, 0, CALL_INDIRECT, VOID) /* 343 */
ENTRY("", 344, no_syscall, 0, CALL_INDIRECT, VOID) /* 344 */
ENTRY("", 345, no_syscall, 0, CALL_INDIRECT, VOID) /* 345 */
ENTRY("", 346, no_syscall, 0, CALL_INDIRECT, VOID) /* 346 */
ENTRY("", 347, no_syscall, 0, CALL_INDIRECT, VOID) /* 347 */
ENTRY("", 348, no_syscall, 0, CALL_INDIRECT, VOID) /* 348 */
ENTRY("", 349, no_syscall, 0, CALL_INDIRECT, VOID) /* 349 */
ENTRY("audit", SYS_audit, audit, 2, CALL_DIRECT, PTR, INT) /* 350 */
ENTRY("auditon", SYS_auditon, auditon, 3, CALL_DIRECT, INT, PTR, INT) /* 351 */
ENTRY("", 352, no_syscall, 0, CALL_INDIRECT, VOID) /* 352 */
ENTRY("getauid", SYS_getauid, getauid, 1, CALL_DIRECT, PTR) /* 353 */
ENTRY("setauid", SYS_setauid, setauid, 1, CALL_DIRECT, PTR) /* 354 */
ENTRY("getaudit", SYS_getaudit, getaudit, 1, CALL_DIRECT, PTR) /* 355 */
ENTRY("setaudit", SYS_setaudit, setaudit, 1, CALL_DIRECT, PTR) /* 356 */
ENTRY("getaudit_addr", SYS_getaudit_addr, getaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 357 */
ENTRY("setaudit_addr", SYS_setaudit_addr, setaudit_addr, 2, CALL_DIRECT, PTR, INT) /* 358 */
ENTRY("auditctl", SYS_auditctl, auditctl, 1, CALL_DIRECT, PTR) /* 359 */
ENTRY("", 360, no_syscall, 0, CALL_INDIRECT, VOID) /* 360 */
ENTRY("", 361, no_syscall, 0, CALL_INDIRECT, VOID) /* 361 */
ENTRY("kqueue", SYS_kqueue, kqueue, 0, CALL_DIRECT, VOID) /* 362 */
ENTRY("kevent", SYS_kevent, kevent, 6, CALL_DIRECT, INT, PTR, INT, PTR, INT, PTR) /* 363 */
ENTRY("lchown", SYS_lchown, lchown, 3, CALL_DIRECT, PTR, INT , INT) /* 364 */
ENTRY("stack_snapshot", SYS_stack_snapshot, unimpl_unix_syscall, 4, CALL_INDIRECT, VOID) /* 365 */
ENTRY("", 366, no_syscall, 0, CALL_INDIRECT, VOID) /* 366 */
ENTRY("", 367, no_syscall, 0, CALL_INDIRECT, VOID) /* 367 */
ENTRY("", 368, no_syscall, 0, CALL_INDIRECT, VOID) /* 368 */
ENTRY("", 369, no_syscall, 0, CALL_INDIRECT, VOID) /* 369 */

View file

@ -1 +0,0 @@
# Default configuration for i386-darwin-user

View file

@ -1,3 +0,0 @@
# Default configuration for ppc-darwin-user
CONFIG_GDBSTUB_XML=y

View file

@ -2270,7 +2270,6 @@ so should only be used with trusted guest OS.
@menu @menu
* Supported Operating Systems :: * Supported Operating Systems ::
* Linux User space emulator:: * Linux User space emulator::
* Mac OS X/Darwin User space emulator ::
* BSD User space emulator :: * BSD User space emulator ::
@end menu @end menu
@ -2283,8 +2282,6 @@ The following OS are supported in user space emulation:
@item @item
Linux (referred as qemu-linux-user) Linux (referred as qemu-linux-user)
@item @item
Mac OS X/Darwin (referred as qemu-darwin-user)
@item
BSD (referred as qemu-bsd-user) BSD (referred as qemu-bsd-user)
@end itemize @end itemize
@ -2489,93 +2486,6 @@ The binary format is detected automatically.
@command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and @command{qemu-sparc64} can execute some Sparc64 (Sparc64 CPU, 64 bit ABI) and
SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI). SPARC32PLUS binaries (Sparc64 CPU, 32 bit ABI).
@node Mac OS X/Darwin User space emulator
@section Mac OS X/Darwin User space emulator
@menu
* Mac OS X/Darwin Status::
* Mac OS X/Darwin Quick Start::
* Mac OS X/Darwin Command line options::
@end menu
@node Mac OS X/Darwin Status
@subsection Mac OS X/Darwin Status
@itemize @minus
@item
target x86 on x86: Most apps (Cocoa and Carbon too) works. [1]
@item
target PowerPC on x86: Not working as the ppc commpage can't be mapped (yet!)
@item
target PowerPC on PowerPC: Most apps (Cocoa and Carbon too) works. [1]
@item
target x86 on PowerPC: most utilities work. Cocoa and Carbon apps are not yet supported.
@end itemize
[1] If you're host commpage can be executed by qemu.
@node Mac OS X/Darwin Quick Start
@subsection Quick Start
In order to launch a Mac OS X/Darwin process, QEMU needs the process executable
itself and all the target dynamic libraries used by it. If you don't have the FAT
libraries (you're running Mac OS X/ppc) you'll need to obtain it from a Mac OS X
CD or compile them by hand.
@itemize
@item On x86, you can just try to launch any process by using the native
libraries:
@example
qemu-i386 /bin/ls
@end example
or to run the ppc version of the executable:
@example
qemu-ppc /bin/ls
@end example
@item On ppc, you'll have to tell qemu where your x86 libraries (and dynamic linker)
are installed:
@example
qemu-i386 -L /opt/x86_root/ /bin/ls
@end example
@code{-L /opt/x86_root/} tells that the dynamic linker (dyld) path is in
@file{/opt/x86_root/usr/bin/dyld}.
@end itemize
@node Mac OS X/Darwin Command line options
@subsection Command line options
@example
usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
@end example
@table @option
@item -h
Print the help
@item -L path
Set the library root path (default=/)
@item -s size
Set the stack size in bytes (default=524288)
@end table
Debug options:
@table @option
@item -d
Activate log (logfile=/tmp/qemu.log)
@item -p pagesize
Act as if the host page size was 'pagesize' bytes
@item -singlestep
Run the emulation in single step mode.
@end table
@node BSD User space emulator @node BSD User space emulator
@section BSD User space emulator @section BSD User space emulator

View file

@ -112,8 +112,7 @@ QEMU user mode emulation features:
@end itemize @end itemize
Linux user emulator (Linux host only) can be used to launch the Wine Linux user emulator (Linux host only) can be used to launch the Wine
Windows API emulator (@url{http://www.winehq.org}). A Darwin user Windows API emulator (@url{http://www.winehq.org}). A BSD user emulator for BSD
emulator (Darwin hosts only) exists and a BSD user emulator for BSD
hosts is under development. It would also be possible to develop a hosts is under development. It would also be possible to develop a
similar user emulator for Solaris. similar user emulator for Solaris.