From 335d2c1342bb887ac67f1f60cff795f0c06beaca Mon Sep 17 00:00:00 2001 From: David 'Digit' Turner Date: Mon, 21 Mar 2011 22:24:45 +0100 Subject: goldfish_trace: Hook with goldfish_pipe.h functions. Note that this is also forces tracing support during machine initialization. Measurements show that this doesn't have any significant impact on emulation performance. Change-Id: Ie32352659611531ce65ba2c95c5896e2421f509d --- hw/goldfish_trace.c | 98 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 36 deletions(-) (limited to 'hw/goldfish_trace.c') diff --git a/hw/goldfish_trace.c b/hw/goldfish_trace.c index fc338c8..ee51a8b 100644 --- a/hw/goldfish_trace.c +++ b/hw/goldfish_trace.c @@ -15,6 +15,7 @@ */ #include "qemu_file.h" #include "goldfish_trace.h" +#include "goldfish_pipe.h" #include "sysemu.h" #include "trace.h" #ifdef CONFIG_MEMCHECK @@ -22,7 +23,23 @@ #include "memcheck/memcheck_util.h" #endif // CONFIG_MEMCHECK -//#define DEBUG 1 +/* Set to 1 to debug tracing */ +#define DEBUG 0 + +#if DEBUG +# define D(...) printf(__VA_ARGS__), fflush(stdout) +#else +# define D(...) ((void)0) +#endif + +/* Set to 1 to debug PID tracking */ +#define DEBUG_PID 0 + +#if DEBUG_PID +# define DPID(...) printf(__VA_ARGS__), fflush(stdout) +#else +# define DPID(...) ((void)0) +#endif extern void cpu_loop_exit(void); @@ -38,6 +55,7 @@ static unsigned long eoff; // offset in EXE file static unsigned cmdlen; // cmdline length static unsigned pid; // PID (really thread id) static unsigned tgid; // thread group id (really process id) +static unsigned tid; // current thread id (same as pid, most of the time) static unsigned long dsaddr; // dynamic symbol address static unsigned long unmap_start; // start address to unmap @@ -53,32 +71,30 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va switch (offset >> 2) { case TRACE_DEV_REG_SWITCH: // context switch, switch to pid + DPID("QEMU.trace: context switch tid=%u\n", value); if (trace_filename != NULL) { trace_switch(value); -#ifdef DEBUG - printf("QEMU.trace: kernel, context switch %u\n", value); -#endif + D("QEMU.trace: kernel, context switch %u\n", value); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_switch(value); } #endif // CONFIG_MEMCHECK + tid = (unsigned) value; break; case TRACE_DEV_REG_TGID: // save the tgid for the following fork/clone + DPID("QEMU.trace: tgid=%u\n", value); tgid = value; -#ifdef DEBUG if (trace_filename != NULL) { - printf("QEMU.trace: kernel, tgid %u\n", value); + D("QEMU.trace: kernel, tgid %u\n", value); } -#endif break; case TRACE_DEV_REG_FORK: // fork, fork new pid + DPID("QEMU.trace: fork (pid=%d tgid=%d value=%d)\n", pid, tgid, value); if (trace_filename != NULL) { trace_fork(tgid, value); -#ifdef DEBUG - printf("QEMU.trace: kernel, fork %u\n", value); -#endif + D("QEMU.trace: kernel, fork %u\n", value); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { @@ -87,11 +103,10 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_CLONE: // fork, clone new pid (i.e. thread) + DPID("QEMU.trace: clone (pid=%d tgid=%d value=%d)\n", pid, tgid, value); if (trace_filename != NULL) { trace_clone(tgid, value); -#ifdef DEBUG - printf("QEMU.trace: kernel, clone %u\n", value); -#endif + D("QEMU.trace: kernel, clone %u\n", value); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { @@ -112,10 +127,8 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va vstrcpy(value, exec_path, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_init_exec(vstart, vend, eoff, exec_path); -#ifdef DEBUG - printf("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n", - vstart, vend, eoff, exec_path); -#endif + D("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n", + vstart, vend, eoff, exec_path); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { @@ -142,7 +155,7 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va memcheck_set_cmd_line(exec_arg, cmdlen); } #endif // CONFIG_MEMCHECK -#ifdef DEBUG +#if DEBUG || DEBUG_PID if (trace_filename != NULL) { int i; for (i = 0; i < cmdlen; i ++) @@ -154,20 +167,21 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va #endif break; case TRACE_DEV_REG_EXIT: // exit, exit current process with exit code + DPID("QEMU.trace: exit tid=%u\n", value); if (trace_filename != NULL) { trace_exit(value); -#ifdef DEBUG - printf("QEMU.trace: kernel, exit %x\n", value); -#endif + D("QEMU.trace: kernel, exit %x\n", value); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_exit(value); } #endif // CONFIG_MEMCHECK + goldfish_pipe_thread_death((int)tid); break; case TRACE_DEV_REG_NAME: // record thread name vstrcpy(value, exec_path, CLIENT_PAGE_SIZE); + DPID("QEMU.trace: thread name=%s\n", exec_path); // Remove the trailing newline if it exists int len = strlen(exec_path); @@ -176,18 +190,15 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va } if (trace_filename != NULL) { trace_name(exec_path); -#ifdef DEBUG - printf("QEMU.trace: kernel, name %s\n", exec_path); -#endif + D("QEMU.trace: kernel, name %s\n", exec_path); } break; case TRACE_DEV_REG_MMAP_EXEPATH: // mmap, path of EXE, the others are same as execve vstrcpy(value, exec_path, CLIENT_PAGE_SIZE); + DPID("QEMU.trace: mmap exe=%s\n", exec_path); if (trace_filename != NULL) { trace_mmap(vstart, vend, eoff, exec_path); -#ifdef DEBUG - printf("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path); -#endif + D("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { @@ -203,6 +214,7 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va break; case TRACE_DEV_REG_INIT_PID: // init, name the pid that starts before device registered pid = value; + DPID("QEMU.trace: pid=%d\n", value); #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_init_pid(value); @@ -211,11 +223,10 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va break; case TRACE_DEV_REG_INIT_NAME: // init, the comm of the init pid vstrcpy(value, exec_path, CLIENT_PAGE_SIZE); + DPID("QEMU.trace: tgid=%d pid=%d name=%s\n", tgid, pid, exec_path); if (trace_filename != NULL) { trace_init_name(tgid, pid, exec_path); -#ifdef DEBUG - printf("QEMU.trace: kernel, init name %u [%s]\n", pid, exec_path); -#endif + D("QEMU.trace: kernel, init name %u [%s]\n", pid, exec_path); } exec_path[0] = 0; break; @@ -227,18 +238,14 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_dynamic_symbol_add(dsaddr, exec_arg); -#ifdef DEBUG - printf("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, exec_arg); -#endif + D("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, exec_arg); } exec_arg[0] = 0; break; case TRACE_DEV_REG_REMOVE_ADDR: // remove dynamic symbol addr if (trace_filename != NULL) { trace_dynamic_symbol_remove(value); -#ifdef DEBUG - printf("QEMU.trace: dynamic symbol remove %lx\n", dsaddr); -#endif + D("QEMU.trace: dynamic symbol remove %lx\n", dsaddr); } break; @@ -343,9 +350,19 @@ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t va break; #endif // CONFIG_MEMCHECK + case TRACE_DEV_PIPE_COMMAND: + case TRACE_DEV_PIPE_ADDRESS: + case TRACE_DEV_PIPE_SIZE: + case TRACE_DEV_PIPE_CHANNEL: + goldfish_pipe_write(tid, ((offset >> 2) - TRACE_DEV_PIPE_BASE), value); + break; + default: if (offset < 4096) { cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset); + } else { + D("%s: offset=%d (0x%x) value=%d (0x%x)\n", __FUNCTION__, offset, + offset, value, value); } break; } @@ -361,9 +378,18 @@ static uint32_t trace_dev_read(void *opaque, target_phys_addr_t offset) switch (offset >> 2) { case TRACE_DEV_REG_ENABLE: // tracing enable return tracing; + + case TRACE_DEV_PIPE_COMMAND: + case TRACE_DEV_PIPE_ADDRESS: + case TRACE_DEV_PIPE_SIZE: + case TRACE_DEV_PIPE_CHANNEL: + return goldfish_pipe_read(tid, (offset >> 2) - TRACE_DEV_PIPE_BASE); + default: if (offset < 4096) { cpu_abort(cpu_single_env, "trace_dev_read: Bad offset %x\n", offset); + } else { + D("%s: offset=%d (0x%x)\n", __FUNCTION__, offset, offset); } return 0; } -- cgit v1.1