Merge branch 'cocoa-for-upstream' of git://repo.or.cz/qemu/afaerber

* 'cocoa-for-upstream' of git://repo.or.cz/qemu/afaerber:
  Drop darwin-user
  configure: add '--disable-cocoa' switch
  raw-posix: Do not use CONFIG_COCOA macro
This commit is contained in:
Blue Swirl 2012-05-01 09:29:23 +00:00
commit 58b5f5e029
18 changed files with 9 additions and 5439 deletions

View File

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

View File

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

View File

@ -29,7 +29,7 @@
#include "module.h"
#include "block/raw-posix-aio.h"
#ifdef CONFIG_COCOA
#if defined(__APPLE__) && (__MACH__)
#include <paths.h>
#include <sys/param.h>
#include <IOKit/IOKitLib.h>
@ -505,7 +505,7 @@ again:
}
if (size == 0)
#endif
#ifdef CONFIG_COCOA
#if defined(__APPLE__) && defined(__MACH__)
size = LONG_LONG_MAX;
#else
size = lseek(fd, 0LL, SEEK_END);
@ -650,7 +650,7 @@ static BlockDriver bdrv_file = {
/***********************************************/
/* host device */
#ifdef CONFIG_COCOA
#if defined(__APPLE__) && defined(__MACH__)
static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
@ -728,7 +728,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
{
BDRVRawState *s = bs->opaque;
#ifdef CONFIG_COCOA
#if defined(__APPLE__) && defined(__MACH__)
if (strstart(filename, "/dev/cdrom", NULL)) {
kern_return_t kernResult;
io_iterator_t mediaIterator;

30
configure vendored
View File

@ -173,7 +173,6 @@ profiler="no"
cocoa="no"
softmmu="yes"
linux_user="no"
darwin_user="no"
bsd_user="no"
guest_base=""
uname_release=""
@ -424,7 +423,6 @@ Darwin)
else
QEMU_CFLAGS="-mdynamic-no-pic $QEMU_CFLAGS"
fi
darwin_user="yes"
cocoa="yes"
audio_drv_list="coreaudio"
audio_possible_drivers="coreaudio sdl fmod"
@ -714,6 +712,8 @@ for opt do
;;
--enable-profiler) profiler="yes"
;;
--disable-cocoa) cocoa="no"
;;
--enable-cocoa)
cocoa="yes" ;
sdl="no" ;
@ -726,17 +726,12 @@ for opt do
--disable-user)
linux_user="no" ;
bsd_user="no" ;
darwin_user="no"
;;
--enable-user) ;;
--disable-linux-user) linux_user="no"
;;
--enable-linux-user) linux_user="yes"
;;
--disable-darwin-user) darwin_user="no"
;;
--enable-darwin-user) darwin_user="yes"
;;
--disable-bsd-user) bsd_user="no"
;;
--enable-bsd-user) bsd_user="yes"
@ -965,10 +960,6 @@ unicore32-linux-user \
s390x-linux-user \
"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
default_target_list="$default_target_list i386-darwin-user ppc-darwin-user "
fi
# the following are BSD specific
if [ "$bsd_user" = "yes" ] ; then
default_target_list="${default_target_list}\
@ -1027,7 +1018,8 @@ echo " --disable-virtfs disable VirtFS"
echo " --enable-virtfs enable VirtFS"
echo " --disable-vnc disable VNC"
echo " --enable-vnc enable VNC"
echo " --enable-cocoa enable COCOA (Mac OS X only)"
echo " --disable-cocoa disable Cocoa (Mac OS X only)"
echo " --enable-cocoa enable Cocoa (default on Mac OS X)"
echo " --audio-drv-list=LIST set audio drivers list:"
echo " Available drivers: $audio_possible_drivers"
echo " --audio-card-list=LIST set list of emulated audio cards [$audio_card_list]"
@ -1069,8 +1061,6 @@ echo " --enable-user enable supported user emulation targets"
echo " --disable-user disable all user emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
echo " --disable-linux-user disable all linux usermode emulation targets"
echo " --enable-darwin-user enable all darwin usermode emulation targets"
echo " --disable-darwin-user disable all darwin usermode emulation targets"
echo " --enable-bsd-user enable all BSD usermode emulation targets"
echo " --disable-bsd-user disable all BSD usermode emulation targets"
echo " --enable-guest-base enable GUEST_BASE support for usermode"
@ -3469,7 +3459,6 @@ esac
target_softmmu="no"
target_user_only="no"
target_linux_user="no"
target_darwin_user="no"
target_bsd_user="no"
case "$target" in
${target_arch2}-softmmu)
@ -3483,14 +3472,6 @@ case "$target" in
target_user_only="yes"
target_linux_user="yes"
;;
${target_arch2}-darwin-user)
if test "$darwin" != "yes" ; then
echo "ERROR: Target '$target' is only available on a Darwin host"
exit 1
fi
target_user_only="yes"
target_darwin_user="yes"
;;
${target_arch2}-bsd-user)
if test "$bsd" != "yes" ; then
echo "ERROR: Target '$target' is only available on a BSD host"
@ -3744,9 +3725,6 @@ fi
if test "$target_linux_user" = "yes" ; then
echo "CONFIG_LINUX_USER=y" >> $config_target_mak
fi
if test "$target_darwin_user" = "yes" ; then
echo "CONFIG_DARWIN_USER=y" >> $config_target_mak
fi
list=""
if test ! -z "$gdb_xml_files" ; then
for x in $gdb_xml_files; do

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

View File

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