From b92c47c1cc25bafd75d81f121e06b68b35d0beed Mon Sep 17 00:00:00 2001 From: ths Date: Thu, 1 Nov 2007 00:07:38 +0000 Subject: Strace for userland emulation, by Stuart Anderson and Thayne Harbaugh. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3502 c046a42c-6fe2-441c-8c8c-71466251a162 --- linux-user/main.c | 4 ++++ linux-user/qemu.h | 8 ++++++++ linux-user/syscall.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) (limited to 'linux-user') diff --git a/linux-user/main.c b/linux-user/main.c index 88a2e48..6a026b0 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -1980,6 +1980,10 @@ int main(int argc, char **argv) env = cpu_init(); global_env = env; + if(getenv("QEMU_STRACE") ){ + do_strace=1; + } + wrk = environ; while (*(wrk++)) environ_count++; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index e92db6e..22a4fec 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -153,10 +153,18 @@ extern CPUState *global_env; 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, + target_long arg1, target_long arg2, target_long arg3, + target_long arg4, target_long arg5, target_long arg6); +void print_syscall_ret(int num, target_long arg1); +extern int do_strace; + /* signal.c */ void process_pending_signals(void *cpu_env); void signal_init(void); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 6d1997e..07e84d9 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -251,11 +251,18 @@ extern int setresgid(gid_t, gid_t, gid_t); extern int getresgid(gid_t *, gid_t *, gid_t *); extern int setgroups(int, gid_t *); +#define ERRNO_TABLE_SIZE 1200 + +/* target_to_host_errno_table[] is initialized from + * host_to_target_errno_table[] in syscall_init(). */ +static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { +}; + /* * This list is the union of errno values overridden in asm-/errno.h * minus the errnos that are not actually generic to all archs. */ -static uint16_t host_to_target_errno_table[1200] = { +static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { [EIDRM] = TARGET_EIDRM, [ECHRNG] = TARGET_ECHRNG, [EL2NSYNC] = TARGET_EL2NSYNC, @@ -361,7 +368,7 @@ static uint16_t host_to_target_errno_table[1200] = { #ifdef ENOTRECOVERABLE [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, #endif - }; +}; static inline int host_to_target_errno(int err) { @@ -370,6 +377,13 @@ static inline int host_to_target_errno(int err) return err; } +static inline int target_to_host_errno(int err) +{ + if (target_to_host_errno_table[err]) + return target_to_host_errno_table[err]; + return err; +} + static inline abi_long get_errno(abi_long ret) { if (ret == -1) @@ -383,6 +397,11 @@ static inline int is_error(abi_long ret) return (abi_ulong)ret >= (abi_ulong)(-4096); } +char *target_strerror(int err) +{ + return strerror(target_to_host_errno(err)); +} + static abi_ulong target_brk; static abi_ulong target_original_brk; @@ -2465,6 +2484,7 @@ void syscall_init(void) IOCTLEntry *ie; const argtype *arg_type; int size; + int i; #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); @@ -2490,6 +2510,12 @@ void syscall_init(void) ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | (size << TARGET_IOC_SIZESHIFT); } + + /* Build target_to_host_errno_table[] table from + * host_to_target_errno_table[]. */ + for (i=0; i < ERRNO_TABLE_SIZE; i++) + target_to_host_errno_table[host_to_target_errno_table[i]] = i; + /* automatic consistency check if same arch */ #if defined(__i386__) && defined(TARGET_I386) if (ie->target_cmd != ie->host_cmd) { @@ -2588,6 +2614,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #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 @@ -5025,5 +5054,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef DEBUG gemu_log(" = %ld\n", ret); #endif + if(do_strace) + print_syscall_ret(num, ret); return ret; } -- cgit v1.1