⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monitor.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * QEMU monitor *  * Copyright (c) 2003-2004 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"#include "disas.h"#include <dirent.h>//#define DEBUG//#define DEBUG_COMPLETION#ifndef offsetof#define offsetof(type, field) ((size_t) &((type *)0)->field)#endif/* * Supported types: *  * 'F'          filename * 'B'          block device name * 's'          string (accept optional quote) * 'i'          32 bit integer * 'l'          target long (32 or 64 bit) * '/'          optional gdb-like print format (like "/10x") * * '?'          optional type (for 'F', 's' and 'i') * */typedef struct term_cmd_t {    const char *name;    const char *args_type;    void (*handler)();    const char *params;    const char *help;} term_cmd_t;static CharDriverState *monitor_hd;static term_cmd_t term_cmds[];static term_cmd_t info_cmds[];static char term_outbuf[1024];static int term_outbuf_index;static void monitor_start_input(void);CPUState *mon_cpu = NULL;void term_flush(void){    if (term_outbuf_index > 0) {        qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);        term_outbuf_index = 0;    }}/* flush at every end of line or if the buffer is full */void term_puts(const char *str){    int c;    for(;;) {        c = *str++;        if (c == '\0')            break;        term_outbuf[term_outbuf_index++] = c;        if (term_outbuf_index >= sizeof(term_outbuf) ||            c == '\n')            term_flush();    }}void term_vprintf(const char *fmt, va_list ap){    char buf[4096];    vsnprintf(buf, sizeof(buf), fmt, ap);    term_puts(buf);}void term_printf(const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    term_vprintf(fmt, ap);    va_end(ap);}static int monitor_fprintf(FILE *stream, const char *fmt, ...){    va_list ap;    va_start(ap, fmt);    term_vprintf(fmt, ap);    va_end(ap);    return 0;}static int compare_cmd(const char *name, const char *list){    const char *p, *pstart;    int len;    len = strlen(name);    p = list;    for(;;) {        pstart = p;        p = strchr(p, '|');        if (!p)            p = pstart + strlen(pstart);        if ((p - pstart) == len && !memcmp(pstart, name, len))            return 1;        if (*p == '\0')            break;        p++;    }    return 0;}static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name){    term_cmd_t *cmd;    for(cmd = cmds; cmd->name != NULL; cmd++) {        if (!name || !strcmp(name, cmd->name))            term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);    }}static void help_cmd(const char *name){    if (name && !strcmp(name, "info")) {        help_cmd1(info_cmds, "info ", NULL);    } else {        help_cmd1(term_cmds, "", name);        if (name && !strcmp(name, "log")) {            CPULogItem *item;            term_printf("Log items (comma separated):\n");            term_printf("%-10s %s\n", "none", "remove all logs");            for(item = cpu_log_items; item->mask != 0; item++) {                term_printf("%-10s %s\n", item->name, item->help);            }        }    }}static void do_help(const char *name){    help_cmd(name);}static void do_commit(void){    int i;    for (i = 0; i < MAX_DISKS; i++) {        if (bs_table[i]) {            bdrv_commit(bs_table[i]);        }    }}static void do_info(const char *item){    term_cmd_t *cmd;    if (!item)        goto help;    for(cmd = info_cmds; cmd->name != NULL; cmd++) {        if (compare_cmd(item, cmd->name))             goto found;    } help:    help_cmd("info");    return; found:    cmd->handler();}static void do_info_version(void){  term_printf("%s\n", QEMU_VERSION);}static void do_info_block(void){    bdrv_info();}/* get the current CPU defined by the user */int mon_set_cpu(int cpu_index){    CPUState *env;    for(env = first_cpu; env != NULL; env = env->next_cpu) {        if (env->cpu_index == cpu_index) {            mon_cpu = env;            return 0;        }    }    return -1;}CPUState *mon_get_cpu(void){    if (!mon_cpu) {        mon_set_cpu(0);    }    return mon_cpu;}static void do_info_registers(void){    CPUState *env;    env = mon_get_cpu();    if (!env)        return;#ifdef TARGET_I386    cpu_dump_state(env, NULL, monitor_fprintf,                   X86_DUMP_FPU);#else    cpu_dump_state(env, NULL, monitor_fprintf,                    0);#endif}static void do_info_cpus(void){    CPUState *env;    /* just to set the default cpu if not already done */    mon_get_cpu();    for(env = first_cpu; env != NULL; env = env->next_cpu) {        term_printf("%c CPU #%d:",                     (env == mon_cpu) ? '*' : ' ',                    env->cpu_index);#if defined(TARGET_I386)        term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base);        if (env->hflags & HF_HALTED_MASK)            term_printf(" (halted)");#elif defined(TARGET_PPC)        term_printf(" nip=0x" TARGET_FMT_lx, env->nip);        if (env->halted)            term_printf(" (halted)");#elif defined(TARGET_SPARC)        term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);        if (env->halted)            term_printf(" (halted)");#endif        term_printf("\n");    }}static void do_cpu_set(int index){    if (mon_set_cpu(index) < 0)        term_printf("Invalid CPU index\n");}static void do_info_jit(void){    dump_exec_info(NULL, monitor_fprintf);}static void do_info_history (void){    int i;    const char *str;        i = 0;    for(;;) {        str = readline_get_history(i);        if (!str)            break;	term_printf("%d: '%s'\n", i, str);        i++;    }}static void do_quit(void){    exit(0);}static int eject_device(BlockDriverState *bs, int force){    if (bdrv_is_inserted(bs)) {        if (!force) {            if (!bdrv_is_removable(bs)) {                term_printf("device is not removable\n");                return -1;            }            if (bdrv_is_locked(bs)) {                term_printf("device is locked\n");                return -1;            }        }        bdrv_close(bs);    }    return 0;}static void do_eject(int force, const char *filename){    BlockDriverState *bs;    bs = bdrv_find(filename);    if (!bs) {        term_printf("device not found\n");        return;    }    eject_device(bs, force);}static void do_change(const char *device, const char *filename){    BlockDriverState *bs;    int i;    char password[256];    bs = bdrv_find(device);    if (!bs) {        term_printf("device not found\n");        return;    }    if (eject_device(bs, 0) < 0)        return;    bdrv_open(bs, filename, 0);    if (bdrv_is_encrypted(bs)) {        term_printf("%s is encrypted.\n", device);        for(i = 0; i < 3; i++) {            monitor_readline("Password: ", 1, password, sizeof(password));            if (bdrv_set_key(bs, password) == 0)                break;            term_printf("invalid password\n");        }    }}static void do_screen_dump(const char *filename){    vga_hw_screen_dump(filename);}static void do_log(const char *items){    int mask;        if (!strcmp(items, "none")) {        mask = 0;    } else {        mask = cpu_str_to_log_mask(items);        if (!mask) {            help_cmd("log");            return;        }    }    cpu_set_log(mask);}static void do_savevm(const char *filename){    if (qemu_savevm(filename) < 0)        term_printf("I/O error when saving VM to '%s'\n", filename);}static void do_loadvm(const char *filename){    if (qemu_loadvm(filename) < 0)         term_printf("I/O error when loading VM from '%s'\n", filename);}static void do_stop(void){    vm_stop(EXCP_INTERRUPT);}static void do_cont(void){    vm_start();}#ifdef CONFIG_GDBSTUBstatic void do_gdbserver(int has_port, int port){    if (!has_port)        port = DEFAULT_GDBSTUB_PORT;    if (gdbserver_start(port) < 0) {        qemu_printf("Could not open gdbserver socket on port %d\n", port);    } else {        qemu_printf("Waiting gdb connection on port %d\n", port);    }}#endifstatic void term_printc(int c){    term_printf("'");    switch(c) {    case '\'':        term_printf("\\'");        break;    case '\\':        term_printf("\\\\");        break;    case '\n':        term_printf("\\n");        break;    case '\r':        term_printf("\\r");        break;    default:        if (c >= 32 && c <= 126) {            term_printf("%c", c);        } else {            term_printf("\\x%02x", c);        }        break;    }    term_printf("'");}static void memory_dump(int count, int format, int wsize,                         target_ulong addr, int is_physical){    CPUState *env;    int nb_per_line, l, line_size, i, max_digits, len;    uint8_t buf[16];    uint64_t v;    if (format == 'i') {        int flags;        flags = 0;        env = mon_get_cpu();        if (!env && !is_physical)            return;#ifdef TARGET_I386        if (wsize == 2) {            flags = 1;        } else if (wsize == 4) {            flags = 0;        } else {            /* as default we use the current CS size */            flags = 0;            if (env) {#ifdef TARGET_X86_64                if ((env->efer & MSR_EFER_LMA) &&                     (env->segs[R_CS].flags & DESC_L_MASK))                    flags = 2;                else#endif                if (!(env->segs[R_CS].flags & DESC_B_MASK))                    flags = 1;            }        }#endif        monitor_disas(env, addr, count, is_physical, flags);        return;    }    len = wsize * count;    if (wsize == 1)        line_size = 8;    else        line_size = 16;    nb_per_line = line_size / wsize;    max_digits = 0;    switch(format) {    case 'o':        max_digits = (wsize * 8 + 2) / 3;        break;    default:    case 'x':        max_digits = (wsize * 8) / 4;        break;    case 'u':    case 'd':        max_digits = (wsize * 8 * 10 + 32) / 33;        break;    case 'c':        wsize = 1;        break;    }    while (len > 0) {        term_printf(TARGET_FMT_lx ":", addr);        l = len;        if (l > line_size)            l = line_size;        if (is_physical) {            cpu_physical_memory_rw(addr, buf, l, 0);        } else {            env = mon_get_cpu();            if (!env)                break;            cpu_memory_rw_debug(env, addr, buf, l, 0);        }        i = 0;         while (i < l) {            switch(wsize) {            default:            case 1:                v = ldub_raw(buf + i);                break;            case 2:                v = lduw_raw(buf + i);                break;            case 4:                v = (uint32_t)ldl_raw(buf + i);                break;            case 8:                v = ldq_raw(buf + i);                break;            }            term_printf(" ");            switch(format) {            case 'o':                term_printf("%#*llo", max_digits, v);                break;            case 'x':                term_printf("0x%0*llx", max_digits, v);                break;            case 'u':                term_printf("%*llu", max_digits, v);                break;            case 'd':                term_printf("%*lld", max_digits, v);                break;            case 'c':                term_printc(v);                break;            }            i += wsize;        }        term_printf("\n");        addr += l;        len -= l;    }}#if TARGET_LONG_BITS == 64#define GET_TLONG(h, l) (((uint64_t)(h) << 32) | (l))#else#define GET_TLONG(h, l) (l)#endifstatic void do_memory_dump(int count, int format, int size,                            uint32_t addrh, uint32_t addrl){    target_long addr = GET_TLONG(addrh, addrl);    memory_dump(count, format, size, addr, 0);}static void do_physical_memory_dump(int count, int format, int size,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -