Commit b92c47c1cc25bafd75d81f121e06b68b35d0beed
1 parent
fc0d441e
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
Showing
4 changed files
with
46 additions
and
3 deletions
Makefile.target
| @@ -259,7 +259,7 @@ main.o: BASE_CFLAGS+=-p | @@ -259,7 +259,7 @@ main.o: BASE_CFLAGS+=-p | ||
| 259 | endif | 259 | endif |
| 260 | 260 | ||
| 261 | ifdef CONFIG_LINUX_USER | 261 | ifdef CONFIG_LINUX_USER |
| 262 | -OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \ | 262 | +OBJS= main.o syscall.o strace.o mmap.o signal.o path.o osdep.o thunk.o \ |
| 263 | elfload.o linuxload.o | 263 | elfload.o linuxload.o |
| 264 | LIBS+= $(AIOLIBS) | 264 | LIBS+= $(AIOLIBS) |
| 265 | ifdef TARGET_HAS_BFLT | 265 | ifdef TARGET_HAS_BFLT |
linux-user/main.c
| @@ -1980,6 +1980,10 @@ int main(int argc, char **argv) | @@ -1980,6 +1980,10 @@ int main(int argc, char **argv) | ||
| 1980 | env = cpu_init(); | 1980 | env = cpu_init(); |
| 1981 | global_env = env; | 1981 | global_env = env; |
| 1982 | 1982 | ||
| 1983 | + if(getenv("QEMU_STRACE") ){ | ||
| 1984 | + do_strace=1; | ||
| 1985 | + } | ||
| 1986 | + | ||
| 1983 | wrk = environ; | 1987 | wrk = environ; |
| 1984 | while (*(wrk++)) | 1988 | while (*(wrk++)) |
| 1985 | environ_count++; | 1989 | environ_count++; |
linux-user/qemu.h
| @@ -153,10 +153,18 @@ extern CPUState *global_env; | @@ -153,10 +153,18 @@ extern CPUState *global_env; | ||
| 153 | void cpu_loop(CPUState *env); | 153 | void cpu_loop(CPUState *env); |
| 154 | void init_paths(const char *prefix); | 154 | void init_paths(const char *prefix); |
| 155 | const char *path(const char *pathname); | 155 | const char *path(const char *pathname); |
| 156 | +char *target_strerror(int err); | ||
| 156 | 157 | ||
| 157 | extern int loglevel; | 158 | extern int loglevel; |
| 158 | extern FILE *logfile; | 159 | extern FILE *logfile; |
| 159 | 160 | ||
| 161 | +/* strace.c */ | ||
| 162 | +void print_syscall(int num, | ||
| 163 | + target_long arg1, target_long arg2, target_long arg3, | ||
| 164 | + target_long arg4, target_long arg5, target_long arg6); | ||
| 165 | +void print_syscall_ret(int num, target_long arg1); | ||
| 166 | +extern int do_strace; | ||
| 167 | + | ||
| 160 | /* signal.c */ | 168 | /* signal.c */ |
| 161 | void process_pending_signals(void *cpu_env); | 169 | void process_pending_signals(void *cpu_env); |
| 162 | void signal_init(void); | 170 | void signal_init(void); |
linux-user/syscall.c
| @@ -251,11 +251,18 @@ extern int setresgid(gid_t, gid_t, gid_t); | @@ -251,11 +251,18 @@ extern int setresgid(gid_t, gid_t, gid_t); | ||
| 251 | extern int getresgid(gid_t *, gid_t *, gid_t *); | 251 | extern int getresgid(gid_t *, gid_t *, gid_t *); |
| 252 | extern int setgroups(int, gid_t *); | 252 | extern int setgroups(int, gid_t *); |
| 253 | 253 | ||
| 254 | +#define ERRNO_TABLE_SIZE 1200 | ||
| 255 | + | ||
| 256 | +/* target_to_host_errno_table[] is initialized from | ||
| 257 | + * host_to_target_errno_table[] in syscall_init(). */ | ||
| 258 | +static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { | ||
| 259 | +}; | ||
| 260 | + | ||
| 254 | /* | 261 | /* |
| 255 | * This list is the union of errno values overridden in asm-<arch>/errno.h | 262 | * This list is the union of errno values overridden in asm-<arch>/errno.h |
| 256 | * minus the errnos that are not actually generic to all archs. | 263 | * minus the errnos that are not actually generic to all archs. |
| 257 | */ | 264 | */ |
| 258 | -static uint16_t host_to_target_errno_table[1200] = { | 265 | +static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { |
| 259 | [EIDRM] = TARGET_EIDRM, | 266 | [EIDRM] = TARGET_EIDRM, |
| 260 | [ECHRNG] = TARGET_ECHRNG, | 267 | [ECHRNG] = TARGET_ECHRNG, |
| 261 | [EL2NSYNC] = TARGET_EL2NSYNC, | 268 | [EL2NSYNC] = TARGET_EL2NSYNC, |
| @@ -361,7 +368,7 @@ static uint16_t host_to_target_errno_table[1200] = { | @@ -361,7 +368,7 @@ static uint16_t host_to_target_errno_table[1200] = { | ||
| 361 | #ifdef ENOTRECOVERABLE | 368 | #ifdef ENOTRECOVERABLE |
| 362 | [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, | 369 | [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, |
| 363 | #endif | 370 | #endif |
| 364 | - }; | 371 | +}; |
| 365 | 372 | ||
| 366 | static inline int host_to_target_errno(int err) | 373 | static inline int host_to_target_errno(int err) |
| 367 | { | 374 | { |
| @@ -370,6 +377,13 @@ static inline int host_to_target_errno(int err) | @@ -370,6 +377,13 @@ static inline int host_to_target_errno(int err) | ||
| 370 | return err; | 377 | return err; |
| 371 | } | 378 | } |
| 372 | 379 | ||
| 380 | +static inline int target_to_host_errno(int err) | ||
| 381 | +{ | ||
| 382 | + if (target_to_host_errno_table[err]) | ||
| 383 | + return target_to_host_errno_table[err]; | ||
| 384 | + return err; | ||
| 385 | +} | ||
| 386 | + | ||
| 373 | static inline abi_long get_errno(abi_long ret) | 387 | static inline abi_long get_errno(abi_long ret) |
| 374 | { | 388 | { |
| 375 | if (ret == -1) | 389 | if (ret == -1) |
| @@ -383,6 +397,11 @@ static inline int is_error(abi_long ret) | @@ -383,6 +397,11 @@ static inline int is_error(abi_long ret) | ||
| 383 | return (abi_ulong)ret >= (abi_ulong)(-4096); | 397 | return (abi_ulong)ret >= (abi_ulong)(-4096); |
| 384 | } | 398 | } |
| 385 | 399 | ||
| 400 | +char *target_strerror(int err) | ||
| 401 | +{ | ||
| 402 | + return strerror(target_to_host_errno(err)); | ||
| 403 | +} | ||
| 404 | + | ||
| 386 | static abi_ulong target_brk; | 405 | static abi_ulong target_brk; |
| 387 | static abi_ulong target_original_brk; | 406 | static abi_ulong target_original_brk; |
| 388 | 407 | ||
| @@ -2465,6 +2484,7 @@ void syscall_init(void) | @@ -2465,6 +2484,7 @@ void syscall_init(void) | ||
| 2465 | IOCTLEntry *ie; | 2484 | IOCTLEntry *ie; |
| 2466 | const argtype *arg_type; | 2485 | const argtype *arg_type; |
| 2467 | int size; | 2486 | int size; |
| 2487 | + int i; | ||
| 2468 | 2488 | ||
| 2469 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); | 2489 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); |
| 2470 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); | 2490 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); |
| @@ -2490,6 +2510,12 @@ void syscall_init(void) | @@ -2490,6 +2510,12 @@ void syscall_init(void) | ||
| 2490 | ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | | 2510 | ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | |
| 2491 | (size << TARGET_IOC_SIZESHIFT); | 2511 | (size << TARGET_IOC_SIZESHIFT); |
| 2492 | } | 2512 | } |
| 2513 | + | ||
| 2514 | + /* Build target_to_host_errno_table[] table from | ||
| 2515 | + * host_to_target_errno_table[]. */ | ||
| 2516 | + for (i=0; i < ERRNO_TABLE_SIZE; i++) | ||
| 2517 | + target_to_host_errno_table[host_to_target_errno_table[i]] = i; | ||
| 2518 | + | ||
| 2493 | /* automatic consistency check if same arch */ | 2519 | /* automatic consistency check if same arch */ |
| 2494 | #if defined(__i386__) && defined(TARGET_I386) | 2520 | #if defined(__i386__) && defined(TARGET_I386) |
| 2495 | if (ie->target_cmd != ie->host_cmd) { | 2521 | if (ie->target_cmd != ie->host_cmd) { |
| @@ -2588,6 +2614,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | @@ -2588,6 +2614,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||
| 2588 | #ifdef DEBUG | 2614 | #ifdef DEBUG |
| 2589 | gemu_log("syscall %d", num); | 2615 | gemu_log("syscall %d", num); |
| 2590 | #endif | 2616 | #endif |
| 2617 | + if(do_strace) | ||
| 2618 | + print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); | ||
| 2619 | + | ||
| 2591 | switch(num) { | 2620 | switch(num) { |
| 2592 | case TARGET_NR_exit: | 2621 | case TARGET_NR_exit: |
| 2593 | #ifdef HAVE_GPROF | 2622 | #ifdef HAVE_GPROF |
| @@ -5025,5 +5054,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | @@ -5025,5 +5054,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, | ||
| 5025 | #ifdef DEBUG | 5054 | #ifdef DEBUG |
| 5026 | gemu_log(" = %ld\n", ret); | 5055 | gemu_log(" = %ld\n", ret); |
| 5027 | #endif | 5056 | #endif |
| 5057 | + if(do_strace) | ||
| 5058 | + print_syscall_ret(num, ret); | ||
| 5028 | return ret; | 5059 | return ret; |
| 5029 | } | 5060 | } |