?? monitor.c
字號:
/* * 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 "hw/hw.h"#include "hw/usb.h"#include "hw/pcmcia.h"#include "hw/pc.h"#include "hw/pci.h"#include "gdbstub.h"#include "net.h"#include "qemu-char.h"#include "sysemu.h"#include "console.h"#include "block.h"#include "audio/audio.h"#include "disas.h"#include <dirent.h>#ifdef CONFIG_PROFILER#include "qemu-timer.h" /* for ticks_per_sec */#endif//#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;#define MAX_MON 4static CharDriverState *monitor_hd[MAX_MON];static int hide_banner;static term_cmd_t term_cmds[];static term_cmd_t info_cmds[];static uint8_t term_outbuf[1024];static int term_outbuf_index;static void monitor_start_input(void);CPUState *mon_cpu = NULL;void term_flush(void){ int i; if (term_outbuf_index > 0) { for (i = 0; i < MAX_MON; i++) if (monitor_hd[i] && monitor_hd[i]->focus == 0) qemu_chr_write(monitor_hd[i], 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){ char c; for(;;) { c = *str++; if (c == '\0') break; if (c == '\n') term_outbuf[term_outbuf_index++] = '\r'; term_outbuf[term_outbuf_index++] = c; if (term_outbuf_index >= (sizeof(term_outbuf) - 1) || 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);}void term_print_filename(const char *filename){ int i; for (i = 0; filename[i]; i++) { switch (filename[i]) { case ' ': case '"': case '\\': term_printf("\\%c", filename[i]); break; case '\t': term_printf("\\t"); break; case '\r': term_printf("\\r"); break; case '\n': term_printf("\\n"); break; default: term_printf("%c", filename[i]); break; } }}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(const char *device){ int i, all_devices; all_devices = !strcmp(device, "all"); for (i = 0; i < nb_drives; i++) { if (all_devices || !strcmp(bdrv_get_device_name(drives_table[i].bdrv), device)) bdrv_commit(drives_table[i].bdrv); }}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_name(void){ if (qemu_name) term_printf("%s\n", qemu_name);}static void do_info_block(void){ bdrv_info();}static void do_info_blockstats(void){ bdrv_info_stats();}/* get the current CPU defined by the user */static 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;}static 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)");#elif defined(TARGET_MIPS) term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]); 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++; }}#if defined(TARGET_PPC)/* XXX: not implemented in other targets */static void do_info_cpu_stats (void){ CPUState *env; env = mon_get_cpu(); cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);}#endifstatic 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_block(const char *device, const char *filename){ BlockDriverState *bs; 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); qemu_key_check(bs, filename);}static void do_change_vnc(const char *target){ if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { char password[9]; monitor_readline("Password: ", 1, password, sizeof(password)-1); password[sizeof(password)-1] = '\0'; if (vnc_display_password(NULL, password) < 0) term_printf("could not set VNC server password\n"); } else { if (vnc_display_open(NULL, target) < 0) term_printf("could not start VNC server on %s\n", target); }}static void do_change(const char *device, const char *target){ if (strcmp(device, "vnc") == 0) { do_change_vnc(target); } else { do_change_block(device, target); }}static void do_screen_dump(const char *filename){ vga_hw_screen_dump(filename);}static void do_logfile(const char *filename){ cpu_set_log_filename(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_stop(void){ vm_stop(EXCP_INTERRUPT);}static void do_cont(void){ vm_start();}#ifdef CONFIG_GDBSTUBstatic void do_gdbserver(const char *port){ if (!port) port = DEFAULT_GDBSTUB_PORT; if (gdbserver_start(port) < 0) { qemu_printf("Could not open gdbserver socket on port '%s'\n", port); } else { qemu_printf("Waiting gdb connection on port '%s'\n", port); }}#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -