trace.c revision b91980562344f6a3b719bfe4be007fa9406e585f
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Virtual hardware for bridging the FUSE kernel module
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the emulated OS and outside file system
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu_file.h"
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "goldfish_trace.h"
185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#include "memcheck/memcheck.h"
205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG   1
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern void cpu_loop_exit(void);
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern int tracing;
275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkineextern const char *trace_filename;
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for execve */
30b91980562344f6a3b719bfe4be007fa9406e585fDavid Turnerstatic char exec_path[CLIENT_PAGE_SIZE];
31b91980562344f6a3b719bfe4be007fa9406e585fDavid Turnerstatic char exec_arg[CLIENT_PAGE_SIZE];
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned long vstart;    // VM start
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned long vend;      // VM end
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned long eoff;      // offset in EXE file
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned cmdlen;         // cmdline length
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned pid;            // PID (really thread id)
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned tgid;           // thread group id (really process id)
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned long dsaddr;    // dynamic symbol address
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic unsigned long unmap_start; // start address to unmap
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* for context switch */
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//static unsigned long cs_pid;    // context switch PID
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* I/O write */
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trace_dev_state *s = (trace_dev_state *)opaque;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (offset >> 2) {
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_SWITCH:  // context switch, switch to pid
515389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_switch(value);
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, context switch %u\n", value);
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_switch(value);
605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_TGID:    // save the tgid for the following fork/clone
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        tgid = value;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, tgid %u\n", value);
685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_FORK:    // fork, fork new pid
725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
735389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_fork(tgid, value);
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, fork %u\n", value);
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
785389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
795389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
805389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_fork(tgid, value);
815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
825389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_CLONE:    // fork, clone new pid (i.e. thread)
855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_clone(tgid, value);
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, clone %u\n", value);
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_clone(tgid, value);
945389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_EXECVE_VMSTART:  // execve, vstart
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        vstart = value;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_EXECVE_VMEND:    // execve, vend
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        vend = value;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_EXECVE_OFFSET:   // execve, offset in EXE
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        eoff = value;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_EXECVE_EXEPATH:  // init exec, path of EXE
107b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
1085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
109b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_init_exec(vstart, vend, eoff, exec_path);
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
1115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n",
112b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner                   vstart, vend, eoff, exec_path);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
1165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
117b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            if (exec_path[0] == '\0') {
1185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // vstrcpy may fail to copy path. In this case lets do it
1195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // differently.
120b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
1215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            }
122b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
1235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
125b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        exec_path[0] = 0;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_CMDLINE_LEN:     // execve, process cmdline length
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmdlen = value;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_CMDLINE:         // execve, process cmdline
131b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        cpu_memory_rw_debug(cpu_single_env, value, exec_arg, cmdlen, 0);
1325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
133b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_execve(exec_arg, cmdlen);
1345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
1365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
137b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            memcheck_set_cmd_line(exec_arg, cmdlen);
1385389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
1415389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int i;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = 0; i < cmdlen; i ++)
144b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner                if (i != cmdlen - 1 && exec_arg[i] == 0)
145b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner                    exec_arg[i] = ' ';
146b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            printf("QEMU.trace: kernel, execve %s[%d]\n", exec_arg, cmdlen);
147b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            exec_arg[0] = 0;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_EXIT:            // exit, exit current process with exit code
1525389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
1535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_exit(value);
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
1555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: kernel, exit %x\n", value);
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1585389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
1595389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
1605389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_exit(value);
1615389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1625389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_NAME:            // record thread name
165b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        // Remove the trailing newline if it exists
168b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        int len = strlen(exec_path);
169b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        if (exec_path[len - 1] == '\n') {
170b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            exec_path[len - 1] = 0;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
173b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_name(exec_path);
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
175b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            printf("QEMU.trace: kernel, name %s\n", exec_path);
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_MMAP_EXEPATH:    // mmap, path of EXE, the others are same as execve
180b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
1815389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
182b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_mmap(vstart, vend, eoff, exec_path);
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
184b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            printf("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path);
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
1885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
189b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            if (exec_path[0] == '\0') {
1905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // vstrcpy may fail to copy path. In this case lets do it
1915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // differently.
192b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
1935389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            }
194b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
1955389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
1965389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
197b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        exec_path[0] = 0;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_INIT_PID:        // init, name the pid that starts before device registered
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pid = value;
2015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
2025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
2035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_init_pid(value);
2045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_INIT_NAME:       // init, the comm of the init pid
208b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
2095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
210b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_init_name(tgid, pid, exec_path);
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
212b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            printf("QEMU.trace: kernel, init name %u [%s]\n", pid, exec_path);
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
215b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        exec_path[0] = 0;
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_DYN_SYM_ADDR:    // dynamic symbol address
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsaddr = value;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_DYN_SYM:         // add dynamic symbol
222b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
2235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
224b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            trace_dynamic_symbol_add(dsaddr, exec_arg);
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
226b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner            printf("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, exec_arg);
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
229b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        exec_arg[0] = 0;
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_REMOVE_ADDR:         // remove dynamic symbol addr
2325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
2335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_dynamic_symbol_remove(value);
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
2355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            printf("QEMU.trace: dynamic symbol remove %lx\n", dsaddr);
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2375389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_PRINT_STR:       // print string
241b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
242b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        printf("%s", exec_arg);
243b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner        exec_arg[0] = 0;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_PRINT_NUM_DEC:   // print number in decimal
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("%d", value);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_PRINT_NUM_HEX:   // print number in hexical
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf("%x", value);
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_STOP_EMU:        // stop the VM execution
2535389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
2545389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            // To ensure that the number of instructions executed in this
2555389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            // block is correct, we pretend that there was an exception.
2565389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_exception(0);
2575389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_single_env->exception_index = EXCP_HLT;
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_single_env->halted = 1;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_system_shutdown_request();
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cpu_loop_exit();
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_ENABLE:          // tracing enable: 0 = stop, 1 = start
2655389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (value == 1) {
2665389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            if (trace_filename != NULL) {
2675389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                start_tracing();
2685389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            }
2695389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (value == 0) {
2715389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            if (trace_filename != NULL) {
2725389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                stop_tracing();
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2745389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // To ensure that the number of instructions executed in this
2755389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                // block is correct, we pretend that there was an exception.
2765389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                trace_exception(0);
2775389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            }
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_UNMAP_START:
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unmap_start = value;
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_UNMAP_END:
2855389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
2865389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            trace_munmap(unmap_start, value);
2875389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2885389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
2895389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
2905389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_unmap(unmap_start, value);
2915389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
2925389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif  // CONFIG_MEMCHECK
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2959980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    case TRACE_DEV_REG_METHOD_ENTRY:
2969980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    case TRACE_DEV_REG_METHOD_EXIT:
2979980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    case TRACE_DEV_REG_METHOD_EXCEPTION:
298e3ea32ffa04468eddaf9c6ce2d36090f7bf43e49Jack Veenstra    case TRACE_DEV_REG_NATIVE_ENTRY:
299e3ea32ffa04468eddaf9c6ce2d36090f7bf43e49Jack Veenstra    case TRACE_DEV_REG_NATIVE_EXIT:
300e3ea32ffa04468eddaf9c6ce2d36090f7bf43e49Jack Veenstra    case TRACE_DEV_REG_NATIVE_EXCEPTION:
3015389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (trace_filename != NULL) {
3025389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            if (tracing) {
3035389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                int call_type = (offset - 4096) >> 2;
3045389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine                trace_interpreted_method(value, call_type);
3055389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            }
3065389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
3075389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        break;
3085389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
3095389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#ifdef CONFIG_MEMCHECK
3105389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    case TRACE_DEV_REG_MALLOC:
3115389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
3125389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_guest_alloc(value);
3135389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
3145389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        break;
3155389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
3165389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    case TRACE_DEV_REG_FREE_PTR:
3175389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
3185389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_guest_free(value);
3195389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
3205389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        break;
3215389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
3225389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    case TRACE_DEV_REG_QUERY_MALLOC:
3235389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
3245389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_guest_query_malloc(value);
3255389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
3265389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        break;
3275389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
3285389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    case TRACE_DEV_REG_LIBC_INIT:
3295389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
3305389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_guest_libc_initialized(value);
3315389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        }
3325389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        break;
3335389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine
3345389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine    case TRACE_DEV_REG_PRINT_USER_STR:
3355389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine        if (memcheck_enabled) {
3365389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine            memcheck_guest_print_str(value);
3379980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        }
3389980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        break;
3395389aa19033153c09556d1362a8b8a56abccb8f5Vladimir Chtchetkine#endif // CONFIG_MEMCHECK
3409980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
3429980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        if (offset < 4096) {
3439980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra            cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset);
3449980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        }
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* I/O read */
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic uint32_t trace_dev_read(void *opaque, target_phys_addr_t offset)
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trace_dev_state *s = (trace_dev_state *)opaque;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (offset >> 2) {
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case TRACE_DEV_REG_ENABLE:          // tracing enable
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return tracing;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
3589980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        if (offset < 4096) {
3599980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra            cpu_abort(cpu_single_env, "trace_dev_read: Bad offset %x\n", offset);
3609980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra        }
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUReadMemoryFunc *trace_dev_readfn[] = {
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_read,
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_read,
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_read
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CPUWriteMemoryFunc *trace_dev_writefn[] = {
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_write,
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_write,
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   trace_dev_write
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initialize the trace device */
3799980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstravoid trace_dev_init()
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int iomemtype;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    trace_dev_state *s;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s = (trace_dev_state *)qemu_mallocz(sizeof(trace_dev_state));
3859980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.name = "qemu_trace";
3869980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.id = -1;
3879980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.base = 0;       // will be allocated dynamically
3889980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.size = 0x2000;
3899980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.irq = 0;
3909980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    s->dev.irq_count = 0;
3919980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra
3929980bbb9965ee2df42f94aafa817e91835dad406Jack Veenstra    goldfish_device_add(&s->dev, trace_dev_readfn, trace_dev_writefn, s);
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
394b91980562344f6a3b719bfe4be007fa9406e585fDavid Turner    exec_path[0] = exec_arg[0] = '\0';
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
396