Index: qemu/Makefile.target =================================================================== --- qemu.orig/Makefile.target 2007-07-19 01:08:12.000000000 -0400 +++ qemu/Makefile.target 2007-07-19 01:43:18.000000000 -0400 @@ -240,7 +240,7 @@ endif ifdef CONFIG_LINUX_USER -OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \ +OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \ elfload.o linuxload.o LIBS+= $(AIOLIBS) ifdef TARGET_HAS_BFLT Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c 2007-07-19 01:42:43.000000000 -0400 +++ qemu/linux-user/syscall.c 2007-07-19 01:43:18.000000000 -0400 @@ -312,6 +312,11 @@ return (unsigned long)ret >= (unsigned long)(-4096); } +char *target_strerror(int err) +{ + return strerror(host_to_target_errno(err)); +} + static target_ulong target_brk; static target_ulong target_original_brk; @@ -2550,6 +2555,9 @@ #ifdef DEBUG gemu_log("syscall %d", num); #endif + if(do_strace) + print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + switch(num) { case TARGET_NR_exit: #ifdef HAVE_GPROF @@ -4734,6 +4742,8 @@ #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif + if(do_strace) + print_syscall_ret(num, ret); return ret; } Index: qemu/linux-user/main.c =================================================================== --- qemu.orig/linux-user/main.c 2007-07-19 01:42:43.000000000 -0400 +++ qemu/linux-user/main.c 2007-07-19 01:43:18.000000000 -0400 @@ -1880,6 +1880,10 @@ putenv("LD_LIBRARY_PATH=/usr/lib/libfakeroot:/usr/lib64/libfakeroot:/usr/lib32/libfakeroot"); } + if(getenv("QEMU_STRACE") ){ + do_strace=1; + } + wrk = environ; while (*(wrk++)) environ_count++; Index: qemu/linux-user/qemu.h =================================================================== --- qemu.orig/linux-user/qemu.h 2007-07-19 01:42:43.000000000 -0400 +++ qemu/linux-user/qemu.h 2007-07-19 01:43:18.000000000 -0400 @@ -138,10 +138,16 @@ void cpu_loop(CPUState *env); void init_paths(const char *prefix); const char *path(const char *pathname); +char *target_strerror(int err); extern int loglevel; extern FILE *logfile; +/* strace.c */ +void print_syscall(int num, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6); +void print_syscall_ret(int num, long arg1); +extern int do_strace; + /* signal.c */ void process_pending_signals(void *cpu_env); void signal_init(void); Index: qemu/linux-user/strace.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ qemu/linux-user/strace.c 2007-07-19 01:43:18.000000000 -0400 @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include +#include +#include "qemu.h" + +int do_strace=0; + +struct syscallname { + int nr; + char *name; + char *format; + void (*call)(struct syscallname *,long, long, long, long, long, long); + void (*result)(struct syscallname *,long); +}; + +/* + * Utility functions + */ +static void +print_ipc_cmd(int cmd) +{ +#define output_cmd(val) \ +if( cmd == val ) { \ + gemu_log(#val); \ + return; \ + } \ + +cmd &= 0xff; + +/* General IPC commands */ +output_cmd( IPC_RMID ); +output_cmd( IPC_SET ); +output_cmd( IPC_STAT ); +output_cmd( IPC_INFO ); +/* msgctl() commands */ +#ifdef __USER_MISC +output_cmd( MSG_STAT ); +output_cmd( MSG_INFO ); +#endif +/* shmctl() commands */ +output_cmd( SHM_LOCK ); +output_cmd( SHM_UNLOCK ); +output_cmd( SHM_STAT ); +output_cmd( SHM_INFO ); +/* semctl() commands */ +output_cmd( GETPID ); +output_cmd( GETVAL ); +output_cmd( GETALL ); +output_cmd( GETNCNT ); +output_cmd( GETZCNT ); +output_cmd( SETVAL ); +output_cmd( SETALL ); +output_cmd( SEM_STAT ); +output_cmd( SEM_INFO ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); +output_cmd( IPC_RMID ); + +/* Some value we don't recognize */ +gemu_log("%d",cmd); +} + +/* + * Sysycall specific output functions + */ +static void +print_newselect(struct syscallname *name, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +long rfds=0,wfds=0,efds=0; + +if( arg2 ) + rfds = *(long *)arg2; +if( arg3 ) + wfds = *(long *)arg3; +if( arg4 ) + efds = *(long *)arg4; + +gemu_log("%s(%d,[%lX],[%lX],[%lX],%p)",name->name, arg1,rfds,wfds,efds,arg5); +} + +static void +print_semctl(struct syscallname *name, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +gemu_log("%s(%d,%d,",name->name, arg1, arg2); +print_ipc_cmd(arg3); +gemu_log(",%p)",arg4); +} + +static void +print_ipc(struct syscallname *name, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +switch(arg1) { + case IPCOP_semctl: + name->name = "semctl"; + print_semctl(name,arg2,arg3,arg4,arg5,arg6,0); + break; + default: + gemu_log("%s(%d,%d,%d,%d)",name->name, arg1, arg2,arg3,arg4); + } +} + +/* + * Variants for the return valueoutput function + */ + +static void +print_syscall_ret_addr(struct syscallname *name, long ret) +{ +if( ret == -1 ) { + gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno)); + } else { + gemu_log(" = %x\n", ret); + } +} + +static void +print_syscall_ret_raw(struct syscallname *name, long ret) +{ + gemu_log(" = %x\n", ret); +} + +/* + * An array of all of the syscalls we know about + */ + +static struct syscallname scnames[] = { +#include "strace.list" +}; + +static int nsyscalls = sizeof(scnames)/sizeof(struct syscallname); + +/* + * The public interface to this module. + */ +void +print_syscall(int num, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +int i; +char *format="%s(%ld,%ld,%ld,%ld,%ld,%ld)"; + +for(i=0;i