]> git.proxmox.com Git - qemu.git/commitdiff
Strace for userland emulation, by Stuart Anderson and Thayne Harbaugh.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 1 Nov 2007 00:07:38 +0000 (00:07 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Thu, 1 Nov 2007 00:07:38 +0000 (00:07 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3502 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile.target
linux-user/main.c
linux-user/qemu.h
linux-user/syscall.c

index 33dc285bb695b608c1dce42970e4c8284c1efa72..07047c18a84c3713250c15514bea28643afb52c5 100644 (file)
@@ -259,7 +259,7 @@ main.o: BASE_CFLAGS+=-p
 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 88a2e4886346b83e17950a9abf899cf48550c480..6a026b012b717f7876cbc0f380b9a11b3e70b3b2 100644 (file)
@@ -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++;
index e92db6ee644264b8eae07499a7c057784d6f872c..22a4fec61dc93cf1495e331381b34637ecd6b2f1 100644 (file)
@@ -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);
index 6d1997e09a7732203190b5f1ba297ef2c56b9c15..07e84d963250ff2203634baf09daf2c805d092aa 100644 (file)
@@ -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-<arch>/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;
 }