static void goldfish_switch_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
    struct switch_state *s = (struct switch_state *)opaque;

    

    switch(offset) {
        case SW_NAME_PTR:
            safe_memory_rw_debug(cpu_single_env, value, (void*)s->name, strlen(s->name), 1);
            break;

        case SW_STATE:
            if(s->writefn) {
                uint32_t new_state;
                new_state = s->writefn(s->writeopaque, value);
                if(new_state != s->state) {
                    goldfish_switch_set_state(s, new_state);
                }
            }
            else
                cpu_abort (cpu_single_env, "goldfish_switch_write: write to SW_STATE on input\n");
            break;

        case SW_INT_ENABLE:
            value &= 1;
            if(s->state_changed && s->int_enable != value)
                goldfish_device_set_irq(&s->dev, 0, value);
            s->int_enable = value;
            break;

        default:
            cpu_abort (cpu_single_env, "goldfish_switch_write: Bad offset %x\n", offset);
    }
}
Esempio n. 2
0
static void goldfish_bus_write(void *opaque, hwaddr offset, uint32_t value)
{
    struct bus_state *s = (struct bus_state *)opaque;

    switch(offset) {
    case PDEV_BUS_OP:
        switch(value) {
        case PDEV_BUS_OP_INIT:
            goldfish_bus_op_init(s);
            break;
        default:
            cpu_abort(cpu_single_env,
                      "goldfish_bus_write: Bad PDEV_BUS_OP value %x\n",
                      value);
        };
        break;
    case PDEV_BUS_GET_NAME:
        if(s->current) {
            target_ulong name = (target_ulong)(s->name_addr_high | value);
            safe_memory_rw_debug(current_cpu, name, (void*)s->current->name, strlen(s->current->name), 1);
        }
        break;
    case PDEV_BUS_NAME_ADDR_HIGH:
        s->name_addr_high = ((uint64_t)value << 32);
        goldfish_64bit_guest = 1;
        break;
    default:
        cpu_abort(cpu_single_env,
                  "goldfish_bus_write: Bad offset %" HWADDR_PRIx "\n",
                  offset);
    }
}
Esempio n. 3
0
static void goldfish_tty_write(void *opaque, hwaddr offset, uint32_t value)
{
    struct tty_state *s = (struct tty_state *)opaque;

    //printf("goldfish_tty_read %x %x %x\n", offset, value, size);

    switch(offset) {
        case TTY_PUT_CHAR: {
            uint8_t ch = value;
            if(s->cs)
                qemu_chr_write(s->cs, &ch, 1);
        } break;

        case TTY_CMD:
            switch(value) {
                case TTY_CMD_INT_DISABLE:
                    if(s->ready) {
                        if(s->data_count > 0)
                            goldfish_device_set_irq(&s->dev, 0, 0);
                        s->ready = 0;
                    }
                    break;

                case TTY_CMD_INT_ENABLE:
                    if(!s->ready) {
                        if(s->data_count > 0)
                            goldfish_device_set_irq(&s->dev, 0, 1);
                        s->ready = 1;
                    }
                    break;

                case TTY_CMD_WRITE_BUFFER:
                    if(s->cs) {
                        int len;
                        hwaddr  buf;

                        buf = s->ptr;
                        len = s->ptr_len;

                        while (len) {
                            char   temp[64];
                            int    to_write = sizeof(temp);
                            if (to_write > len)
                                to_write = len;

                            safe_memory_rw_debug(cpu_single_env, buf, (uint8_t*)temp, to_write, 0);
                            qemu_chr_write(s->cs, (const uint8_t*)temp, to_write);
                            buf += to_write;
                            len -= to_write;
                        }
                        //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr);
                    }
                    break;

                case TTY_CMD_READ_BUFFER:
                    if(s->ptr_len > s->data_count)
                        cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count);
                    safe_memory_rw_debug(cpu_single_env,s->ptr, s->data, s->ptr_len,1);
                    //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr);
                    if(s->data_count > s->ptr_len)
                        memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len);
                    s->data_count -= s->ptr_len;
                    if(s->data_count == 0 && s->ready)
                        goldfish_device_set_irq(&s->dev, 0, 0);
                    break;

                default:
                    cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value);
            };
            break;

        case TTY_DATA_PTR:
            s->ptr = value;
            break;

        case TTY_DATA_LEN:
            s->ptr_len = value;
            break;

        default:
            cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset);
    }
}
Esempio n. 4
0
/* I/O write */
static void trace_dev_write(void *opaque, hwaddr offset, uint32_t value)
{
    trace_dev_state *s = (trace_dev_state *)opaque;

    (void)s;

    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);
            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;
        if (trace_filename != NULL) {
            D("QEMU.trace: kernel, tgid %u\n", value);
        }
        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);
            D("QEMU.trace: kernel, fork %u\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_fork(tgid, value);
        }
#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);
            D("QEMU.trace: kernel, clone %u\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_clone(tgid, value);
        }
#endif  // CONFIG_MEMCHECK
        break;
    case TRACE_DEV_REG_EXECVE_VMSTART:  // execve, vstart
        vstart = value;
        break;
    case TRACE_DEV_REG_EXECVE_VMEND:    // execve, vend
        vend = value;
        break;
    case TRACE_DEV_REG_EXECVE_OFFSET:   // execve, offset in EXE
        eoff = value;
        break;
    case TRACE_DEV_REG_EXECVE_EXEPATH:  // init exec, path of EXE
        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
        if (trace_filename != NULL) {
            trace_init_exec(vstart, vend, eoff, exec_path);
            D("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n",
              vstart, vend, eoff, exec_path);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            if (exec_path[0] == '\0') {
                // vstrcpy may fail to copy path. In this case lets do it
                // differently.
                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
            }
            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
        }
#endif  // CONFIG_MEMCHECK
        exec_path[0] = 0;
        break;
    case TRACE_DEV_REG_CMDLINE_LEN:     // execve, process cmdline length
        cmdlen = value;
        break;
    case TRACE_DEV_REG_CMDLINE:         // execve, process cmdline
        safe_memory_rw_debug(cpu_single_env, value, (uint8_t*)exec_arg, cmdlen, 0);
        if (trace_filename != NULL) {
            trace_execve(exec_arg, cmdlen);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_set_cmd_line(exec_arg, cmdlen);
        }
#endif  // CONFIG_MEMCHECK
#if DEBUG || DEBUG_PID
        if (trace_filename != NULL) {
            int i;
            for (i = 0; i < cmdlen; i ++)
                if (i != cmdlen - 1 && exec_arg[i] == 0)
                    exec_arg[i] = ' ';
            printf("QEMU.trace: kernel, execve %s[%d]\n", exec_arg, cmdlen);
            exec_arg[0] = 0;
        }
#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);
            D("QEMU.trace: kernel, exit %x\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_exit(value);
        }
#endif  // CONFIG_MEMCHECK
        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);
        if (exec_path[len - 1] == '\n') {
            exec_path[len - 1] = 0;
        }
        if (trace_filename != NULL) {
            trace_name(exec_path);
            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);
            D("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            if (exec_path[0] == '\0') {
                // vstrcpy may fail to copy path. In this case lets do it
                // differently.
                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
            }
            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
        }
#endif  // CONFIG_MEMCHECK
        exec_path[0] = 0;
        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);
        }
#endif  // CONFIG_MEMCHECK
        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);
            D("QEMU.trace: kernel, init name %u [%s]\n", pid, exec_path);
        }
        exec_path[0] = 0;
        break;

    case TRACE_DEV_REG_DYN_SYM_ADDR:    // dynamic symbol address
        dsaddr = value;
        break;
    case TRACE_DEV_REG_DYN_SYM:         // add dynamic symbol
        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
        if (trace_filename != NULL) {
            trace_dynamic_symbol_add(dsaddr, exec_arg);
            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);
            D("QEMU.trace: dynamic symbol remove %lx\n", dsaddr);
        }
        break;

    case TRACE_DEV_REG_PRINT_STR:       // print string
        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
        printf("%s", exec_arg);
        exec_arg[0] = 0;
        break;
    case TRACE_DEV_REG_PRINT_NUM_DEC:   // print number in decimal
        printf("%d", value);
        break;
    case TRACE_DEV_REG_PRINT_NUM_HEX:   // print number in hexical
        printf("%x", value);
        break;

    case TRACE_DEV_REG_STOP_EMU:        // stop the VM execution
        if (trace_filename != NULL) {
            // To ensure that the number of instructions executed in this
            // block is correct, we pretend that there was an exception.
            trace_exception(0);
        }
        cpu_single_env->exception_index = EXCP_HLT;
        cpu_single_env->halted = 1;
        qemu_system_shutdown_request();
        cpu_loop_exit();
        break;

    case TRACE_DEV_REG_ENABLE:          // tracing enable: 0 = stop, 1 = start
        if (value == 1) {
            if (trace_filename != NULL) {
                start_tracing();
            }
        }
        else if (value == 0) {
            if (trace_filename != NULL) {
                stop_tracing();

                // To ensure that the number of instructions executed in this
                // block is correct, we pretend that there was an exception.
                trace_exception(0);
            }
        }
        break;

    case TRACE_DEV_REG_UNMAP_START:
        unmap_start = value;
        break;
    case TRACE_DEV_REG_UNMAP_END:
        if (trace_filename != NULL) {
            trace_munmap(unmap_start, value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_unmap(unmap_start, value);
        }
#endif  // CONFIG_MEMCHECK
        break;

    case TRACE_DEV_REG_METHOD_ENTRY:
    case TRACE_DEV_REG_METHOD_EXIT:
    case TRACE_DEV_REG_METHOD_EXCEPTION:
    case TRACE_DEV_REG_NATIVE_ENTRY:
    case TRACE_DEV_REG_NATIVE_EXIT:
    case TRACE_DEV_REG_NATIVE_EXCEPTION:
        if (trace_filename != NULL) {
            if (tracing) {
                int call_type = (offset - 4096) >> 2;
                trace_interpreted_method(value, call_type);
            }
        }
        break;

#ifdef CONFIG_MEMCHECK
    case TRACE_DEV_REG_MALLOC:
        if (memcheck_enabled) {
            memcheck_guest_alloc(value);
        }
        break;

    case TRACE_DEV_REG_FREE_PTR:
        if (memcheck_enabled) {
            memcheck_guest_free(value);
        }
        break;

    case TRACE_DEV_REG_QUERY_MALLOC:
        if (memcheck_enabled) {
            memcheck_guest_query_malloc(value);
        }
        break;

    case TRACE_DEV_REG_LIBC_INIT:
        if (memcheck_enabled) {
            memcheck_guest_libc_initialized(value);
        }
        break;

    case TRACE_DEV_REG_PRINT_USER_STR:
        if (memcheck_enabled) {
            memcheck_guest_print_str(value);
        }
        break;
#endif // CONFIG_MEMCHECK

    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;
    }
}
static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value)
{
    trace_dev_state *s = (trace_dev_state *)opaque;

    (void)s;

    switch (offset >> 2) {
    case TRACE_DEV_REG_SWITCH:  
        DPID("QEMU.trace: context switch tid=%u\n", value);
        if (trace_filename != NULL) {
            trace_switch(value);
            D("QEMU.trace: kernel, context switch %u\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_switch(value);
        }
#endif  
        tid = (unsigned) value;
        break;
    case TRACE_DEV_REG_TGID:    
        DPID("QEMU.trace: tgid=%u\n", value);
        tgid = value;
        if (trace_filename != NULL) {
            D("QEMU.trace: kernel, tgid %u\n", value);
        }
        break;
    case TRACE_DEV_REG_FORK:    
        DPID("QEMU.trace: fork (pid=%d tgid=%d value=%d)\n", pid, tgid, value);
        if (trace_filename != NULL) {
            trace_fork(tgid, value);
            D("QEMU.trace: kernel, fork %u\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_fork(tgid, value);
        }
#endif  
        break;
    case TRACE_DEV_REG_CLONE:    
        DPID("QEMU.trace: clone (pid=%d tgid=%d value=%d)\n", pid, tgid, value);
        if (trace_filename != NULL) {
            trace_clone(tgid, value);
            D("QEMU.trace: kernel, clone %u\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_clone(tgid, value);
        }
#endif  
        break;
    case TRACE_DEV_REG_EXECVE_VMSTART:  
        vstart = value;
        break;
    case TRACE_DEV_REG_EXECVE_VMEND:    
        vend = value;
        break;
    case TRACE_DEV_REG_EXECVE_OFFSET:   
        eoff = value;
        break;
    case TRACE_DEV_REG_EXECVE_EXEPATH:  
        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
        if (trace_filename != NULL) {
            trace_init_exec(vstart, vend, eoff, exec_path);
            D("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n",
              vstart, vend, eoff, exec_path);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            if (exec_path[0] == '\0') {
                
                
                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
            }
            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
        }
#endif  
        exec_path[0] = 0;
        break;
    case TRACE_DEV_REG_CMDLINE_LEN:     
        cmdlen = value;
        break;
    case TRACE_DEV_REG_CMDLINE:         
        safe_memory_rw_debug(cpu_single_env, value, (uint8_t*)exec_arg, cmdlen, 0);
        if (trace_filename != NULL) {
            trace_execve(exec_arg, cmdlen);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_set_cmd_line(exec_arg, cmdlen);
        }
#endif  
#if DEBUG || DEBUG_PID
        if (trace_filename != NULL) {
            int i;
            for (i = 0; i < cmdlen; i ++)
                if (i != cmdlen - 1 && exec_arg[i] == 0)
                    exec_arg[i] = ' ';
            printf("QEMU.trace: kernel, execve %s[%d]\n", exec_arg, cmdlen);
            exec_arg[0] = 0;
        }
#endif
        break;
    case TRACE_DEV_REG_EXIT:            
        DPID("QEMU.trace: exit tid=%u\n", value);
        if (trace_filename != NULL) {
            trace_exit(value);
            D("QEMU.trace: kernel, exit %x\n", value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_exit(value);
        }
#endif  
        break;
    case TRACE_DEV_REG_NAME:            
        vstrcpy(value, exec_path, CLIENT_PAGE_SIZE);
        DPID("QEMU.trace: thread name=%s\n", exec_path);

        
        int len = strlen(exec_path);
        if (exec_path[len - 1] == '\n') {
            exec_path[len - 1] = 0;
        }
        if (trace_filename != NULL) {
            trace_name(exec_path);
            D("QEMU.trace: kernel, name %s\n", exec_path);
        }
        break;
    case TRACE_DEV_REG_MMAP_EXEPATH:    
        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);
            D("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, exec_path);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            if (exec_path[0] == '\0') {
                
                
                memcheck_get_guest_kernel_string(exec_path, value, CLIENT_PAGE_SIZE);
            }
            memcheck_mmap_exepath(vstart, vend, eoff, exec_path);
        }
#endif  
        exec_path[0] = 0;
        break;
    case TRACE_DEV_REG_INIT_PID:        
        pid = value;
        DPID("QEMU.trace: pid=%d\n", value);
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_init_pid(value);
        }
#endif  
        break;
    case TRACE_DEV_REG_INIT_NAME:       
        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);
            D("QEMU.trace: kernel, init name %u [%s]\n", pid, exec_path);
        }
        exec_path[0] = 0;
        break;

    case TRACE_DEV_REG_DYN_SYM_ADDR:    
        dsaddr = value;
        break;
    case TRACE_DEV_REG_DYN_SYM:         
        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
        if (trace_filename != NULL) {
            trace_dynamic_symbol_add(dsaddr, exec_arg);
            D("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, exec_arg);
        }
        exec_arg[0] = 0;
        break;
    case TRACE_DEV_REG_REMOVE_ADDR:         
        if (trace_filename != NULL) {
            trace_dynamic_symbol_remove(value);
            D("QEMU.trace: dynamic symbol remove %lx\n", dsaddr);
        }
        break;

    case TRACE_DEV_REG_PRINT_STR:       
        vstrcpy(value, exec_arg, CLIENT_PAGE_SIZE);
        printf("%s", exec_arg);
        exec_arg[0] = 0;
        break;
    case TRACE_DEV_REG_PRINT_NUM_DEC:   
        printf("%d", value);
        break;
    case TRACE_DEV_REG_PRINT_NUM_HEX:   
        printf("%x", value);
        break;

    case TRACE_DEV_REG_STOP_EMU:        
        if (trace_filename != NULL) {
            
            
            trace_exception(0);
        }
        cpu_single_env->exception_index = EXCP_HLT;
        cpu_single_env->halted = 1;
        qemu_system_shutdown_request();
        cpu_loop_exit();
        break;

    case TRACE_DEV_REG_ENABLE:          
        if (value == 1) {
            if (trace_filename != NULL) {
                start_tracing();
            }
        }
        else if (value == 0) {
            if (trace_filename != NULL) {
                stop_tracing();

                
                
                trace_exception(0);
            }
        }
        break;

    case TRACE_DEV_REG_UNMAP_START:
        unmap_start = value;
        break;
    case TRACE_DEV_REG_UNMAP_END:
        if (trace_filename != NULL) {
            trace_munmap(unmap_start, value);
        }
#ifdef CONFIG_MEMCHECK
        if (memcheck_enabled) {
            memcheck_unmap(unmap_start, value);
        }
#endif  
        break;

    case TRACE_DEV_REG_METHOD_ENTRY:
    case TRACE_DEV_REG_METHOD_EXIT:
    case TRACE_DEV_REG_METHOD_EXCEPTION:
    case TRACE_DEV_REG_NATIVE_ENTRY:
    case TRACE_DEV_REG_NATIVE_EXIT:
    case TRACE_DEV_REG_NATIVE_EXCEPTION:
        if (trace_filename != NULL) {
            if (tracing) {
                int call_type = (offset - 4096) >> 2;
                trace_interpreted_method(value, call_type);
            }
        }
        break;

#ifdef CONFIG_MEMCHECK
    case TRACE_DEV_REG_MALLOC:
        if (memcheck_enabled) {
            memcheck_guest_alloc(value);
        }
        break;

    case TRACE_DEV_REG_FREE_PTR:
        if (memcheck_enabled) {
            memcheck_guest_free(value);
        }
        break;

    case TRACE_DEV_REG_QUERY_MALLOC:
        if (memcheck_enabled) {
            memcheck_guest_query_malloc(value);
        }
        break;

    case TRACE_DEV_REG_LIBC_INIT:
        if (memcheck_enabled) {
            memcheck_guest_libc_initialized(value);
        }
        break;

    case TRACE_DEV_REG_PRINT_USER_STR:
        if (memcheck_enabled) {
            memcheck_guest_print_str(value);
        }
        break;
#endif 

    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;
    }
}