aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.target2
-rw-r--r--linux-user/main.c4
-rw-r--r--linux-user/qemu.h8
-rw-r--r--linux-user/syscall.c35
4 files changed, 46 insertions, 3 deletions
diff --git a/Makefile.target b/Makefile.target
index 33dc285bb6..07047c18a8 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -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
diff --git a/linux-user/main.c b/linux-user/main.c
index 88a2e48863..6a026b012b 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 e92db6ee64..22a4fec61d 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 6d1997e09a..07e84d9632 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-<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;
}