aboutsummaryrefslogtreecommitdiffstats
path: root/hw/goldfish_trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/goldfish_trace.c')
-rw-r--r--hw/goldfish_trace.c98
1 files changed, 62 insertions, 36 deletions
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;
}