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 | 259 | endif |
260 | 260 | |
261 | 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 | 263 | elfload.o linuxload.o |
264 | 264 | LIBS+= $(AIOLIBS) |
265 | 265 | ifdef TARGET_HAS_BFLT | ... | ... |
linux-user/main.c
linux-user/qemu.h
... | ... | @@ -153,10 +153,18 @@ extern CPUState *global_env; |
153 | 153 | void cpu_loop(CPUState *env); |
154 | 154 | void init_paths(const char *prefix); |
155 | 155 | const char *path(const char *pathname); |
156 | +char *target_strerror(int err); | |
156 | 157 | |
157 | 158 | extern int loglevel; |
158 | 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 | 168 | /* signal.c */ |
161 | 169 | void process_pending_signals(void *cpu_env); |
162 | 170 | void signal_init(void); | ... | ... |
linux-user/syscall.c
... | ... | @@ -251,11 +251,18 @@ extern int setresgid(gid_t, gid_t, gid_t); |
251 | 251 | extern int getresgid(gid_t *, gid_t *, gid_t *); |
252 | 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 | 262 | * This list is the union of errno values overridden in asm-<arch>/errno.h |
256 | 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 | 266 | [EIDRM] = TARGET_EIDRM, |
260 | 267 | [ECHRNG] = TARGET_ECHRNG, |
261 | 268 | [EL2NSYNC] = TARGET_EL2NSYNC, |
... | ... | @@ -361,7 +368,7 @@ static uint16_t host_to_target_errno_table[1200] = { |
361 | 368 | #ifdef ENOTRECOVERABLE |
362 | 369 | [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE, |
363 | 370 | #endif |
364 | - }; | |
371 | +}; | |
365 | 372 | |
366 | 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 | 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 | 387 | static inline abi_long get_errno(abi_long ret) |
374 | 388 | { |
375 | 389 | if (ret == -1) |
... | ... | @@ -383,6 +397,11 @@ static inline int is_error(abi_long ret) |
383 | 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 | 405 | static abi_ulong target_brk; |
387 | 406 | static abi_ulong target_original_brk; |
388 | 407 | |
... | ... | @@ -2465,6 +2484,7 @@ void syscall_init(void) |
2465 | 2484 | IOCTLEntry *ie; |
2466 | 2485 | const argtype *arg_type; |
2467 | 2486 | int size; |
2487 | + int i; | |
2468 | 2488 | |
2469 | 2489 | #define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); |
2470 | 2490 | #define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); |
... | ... | @@ -2490,6 +2510,12 @@ void syscall_init(void) |
2490 | 2510 | ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | |
2491 | 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 | 2519 | /* automatic consistency check if same arch */ |
2494 | 2520 | #if defined(__i386__) && defined(TARGET_I386) |
2495 | 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 | 2614 | #ifdef DEBUG |
2589 | 2615 | gemu_log("syscall %d", num); |
2590 | 2616 | #endif |
2617 | + if(do_strace) | |
2618 | + print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); | |
2619 | + | |
2591 | 2620 | switch(num) { |
2592 | 2621 | case TARGET_NR_exit: |
2593 | 2622 | #ifdef HAVE_GPROF |
... | ... | @@ -5025,5 +5054,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, |
5025 | 5054 | #ifdef DEBUG |
5026 | 5055 | gemu_log(" = %ld\n", ret); |
5027 | 5056 | #endif |
5057 | + if(do_strace) | |
5058 | + print_syscall_ret(num, ret); | |
5028 | 5059 | return ret; |
5029 | 5060 | } | ... | ... |