Commit b92c47c1cc25bafd75d81f121e06b68b35d0beed

Authored by ths
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
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 }