(linenum→info "unix/slp.c:2238")

qemu/0.9.1/monitor.c

    1: /*
    2:  * QEMU monitor
    3:  *
    4:  * Copyright (c) 2003-2004 Fabrice Bellard
    5:  *
    6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
    7:  * of this software and associated documentation files (the "Software"), to deal
    8:  * in the Software without restriction, including without limitation the rights
    9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10:  * copies of the Software, and to permit persons to whom the Software is
   11:  * furnished to do so, subject to the following conditions:
   12:  *
   13:  * The above copyright notice and this permission notice shall be included in
   14:  * all copies or substantial portions of the Software.
   15:  *
   16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   22:  * THE SOFTWARE.
   23:  */
   24: #include "hw/hw.h"
   25: #include "hw/usb.h"
   26: #include "hw/pcmcia.h"
   27: #include "hw/pc.h"
   28: #include "hw/pci.h"
   29: #include "gdbstub.h"
   30: #include "net.h"
   31: #include "qemu-char.h"
   32: #include "sysemu.h"
   33: #include "console.h"
   34: #include "block.h"
   35: #include "audio/audio.h"
   36: #include "disas.h"
   37: #include <dirent.h>
   38: 
   39: #ifdef CONFIG_PROFILER
   40: #include "qemu-timer.h" /* for ticks_per_sec */
   41: #endif
   42: 
   43: //#define DEBUG
   44: //#define DEBUG_COMPLETION
   45: 
   46: #ifndef offsetof
   47: #define offsetof(type, field) ((size_t) &((type *)0)->field)
   48: #endif
   49: 
   50: /*
   51:  * Supported types:
   52:  *
   53:  * 'F'          filename
   54:  * 'B'          block device name
   55:  * 's'          string (accept optional quote)
   56:  * 'i'          32 bit integer
   57:  * 'l'          target long (32 or 64 bit)
   58:  * '/'          optional gdb-like print format (like "/10x")
   59:  *
   60:  * '?'          optional type (for 'F', 's' and 'i')
   61:  *
   62:  */
   63: 
   64: typedef struct term_cmd_t {
   65:     const char *name;
   66:     const char *args_type;
   67:     void (*handler)();
   68:     const char *params;
   69:     const char *help;
   70: } term_cmd_t;
   71: 
   72: #define MAX_MON 4
   73: static CharDriverState *monitor_hd[MAX_MON];
   74: static int hide_banner;
   75: 
   76: static term_cmd_t term_cmds[];
   77: static term_cmd_t info_cmds[];
   78: 
   79: static uint8_t term_outbuf[1024];
   80: static int term_outbuf_index;
   81: 
   82: static void monitor_start_input(void);
   83: 
   84: CPUState *mon_cpu = NULL;
   85: 
   86: void term_flush(void)
   87: {
   88:     int i;
   89:     if (term_outbuf_index > 0) {
   90:         for (i = 0; i < MAX_MON; i++)
   91:             if (monitor_hd[i] && monitor_hd[i]->focus == 0)
   92:                 qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
   93:         term_outbuf_index = 0;
   94:     }
   95: }
   96: 
   97: /* flush at every end of line or if the buffer is full */
   98: void term_puts(const char *str)
   99: {
  100:     char c;
  101:     for(;;) {
  102:         c = *str++;
  103:         if (c == '\0')
  104:             break;
  105:         if (c == '\n')
  106:             term_outbuf[term_outbuf_index++] = '\r';
  107:         term_outbuf[term_outbuf_index++] = c;
  108:         if (term_outbuf_index >= (sizeof(term_outbuf) - 1) ||
  109:             c == '\n')
  110:             term_flush();
  111:     }
  112: }
  113: 
  114: void term_vprintf(const char *fmt, va_list ap)
  115: {
  116:     char buf[4096];
  117:     vsnprintf(buf, sizeof(buf), fmt, ap);
  118:     term_puts(buf);
  119: }
  120: 
  121: void term_printf(const char *fmt, ...)
  122: {
  123:     va_list ap;
  124:     va_start(ap, fmt);
  125:     term_vprintf(fmt, ap);
  126:     va_end(ap);
  127: }
  128: 
  129: void term_print_filename(const char *filename)
  130: {
  131:     int i;
  132: 
  133:     for (i = 0; filename[i]; i++) {
  134:         switch (filename[i]) {
  135:         case ' ':
  136:         case '"':
  137:         case '\\':
  138:             term_printf("\\%c", filename[i]);
  139:             break;
  140:         case '\t':
  141:             term_printf("\\t");
  142:             break;
  143:         case '\r':
  144:             term_printf("\\r");
  145:             break;
  146:         case '\n':
  147:             term_printf("\\n");
  148:             break;
  149:         default:
  150:             term_printf("%c", filename[i]);
  151:             break;
  152:         }
  153:     }
  154: }
  155: 
  156: static int monitor_fprintf(FILE *stream, const char *fmt, ...)
  157: {
  158:     va_list ap;
  159:     va_start(ap, fmt);
  160:     term_vprintf(fmt, ap);
  161:     va_end(ap);
  162:     return 0;
  163: }
  164: 
  165: static int compare_cmd(const char *name, const char *list)
  166: {
  167:     const char *p, *pstart;
  168:     int len;
  169:     len = strlen(name);
  170:     p = list;
  171:     for(;;) {
  172:         pstart = p;
  173:         p = strchr(p, '|');
  174:         if (!p)
  175:             p = pstart + strlen(pstart);
  176:         if ((p - pstart) == len && !memcmp(pstart, name, len))
  177:             return 1;
  178:         if (*p == '\0')
  179:             break;
  180:         p++;
  181:     }
  182:     return 0;
  183: }
  184: 
  185: static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
  186: {
  187:     term_cmd_t *cmd;
  188: 
  189:     for(cmd = cmds; cmd->name != NULL; cmd++) {
  190:         if (!name || !strcmp(name, cmd->name))
  191:             term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
  192:     }
  193: }
  194: 
  195: static void help_cmd(const char *name)
  196: {
  197:     if (name && !strcmp(name, "info")) {
  198:         help_cmd1(info_cmds, "info ", NULL);
  199:     } else {
  200:         help_cmd1(term_cmds, "", name);
  201:         if (name && !strcmp(name, "log")) {
  202:             CPULogItem *item;
  203:             term_printf("Log items (comma separated):\n");
  204:             term_printf("%-10s %s\n", "none", "remove all logs");
  205:             for(item = cpu_log_items; item->mask != 0; item++) {
  206:                 term_printf("%-10s %s\n", item->name, item->help);
  207:             }
  208:         }
  209:     }
  210: }
  211: 
  212: static void do_help(const char *name)
  213: {
  214:     help_cmd(name);
  215: }
  216: 
  217: static void do_commit(const char *device)
  218: {
  219:     int i, all_devices;
  220: 
  221:     all_devices = !strcmp(device, "all");
  222:     for (i = 0; i < nb_drives; i++) {
  223:             if (all_devices ||
  224:                 !strcmp(bdrv_get_device_name(drives_table[i].bdrv), device))
  225:                 bdrv_commit(drives_table[i].bdrv);
  226:     }
  227: }
  228: 
  229: static void do_info(const char *item)
  230: {
  231:     term_cmd_t *cmd;
  232: 
  233:     if (!item)
  234:         goto help;
  235:     for(cmd = info_cmds; cmd->name != NULL; cmd++) {
  236:         if (compare_cmd(item, cmd->name))
  237:             goto found;
  238:     }
  239:  help:
  240:     help_cmd("info");
  241:     return;
  242:  found:
  243:     cmd->handler();
  244: }
  245: 
  246: static void do_info_version(void)
  247: {
  248:   term_printf("%s\n", QEMU_VERSION);
  249: }
  250: 
  251: static void do_info_name(void)
  252: {
  253:     if (qemu_name)
  254:         term_printf("%s\n", qemu_name);
  255: }
  256: 
  257: static void do_info_block(void)
  258: {
  259:     bdrv_info();
  260: }
  261: 
  262: static void do_info_blockstats(void)
  263: {
  264:     bdrv_info_stats();
  265: }
  266: 
  267: /* get the current CPU defined by the user */
  268: static int mon_set_cpu(int cpu_index)
  269: {
  270:     CPUState *env;
  271: 
  272:     for(env = first_cpu; env != NULL; env = env->next_cpu) {
  273:         if (env->cpu_index == cpu_index) {
  274:             mon_cpu = env;
  275:             return 0;
  276:         }
  277:     }
  278:     return -1;
  279: }
  280: 
  281: static CPUState *mon_get_cpu(void)
  282: {
  283:     if (!mon_cpu) {
  284:         mon_set_cpu(0);
  285:     }
  286:     return mon_cpu;
  287: }
  288: 
  289: static void do_info_registers(void)
  290: {
  291:     CPUState *env;
  292:     env = mon_get_cpu();
  293:     if (!env)
  294:         return;
  295: #ifdef TARGET_I386
  296:     cpu_dump_state(env, NULL, monitor_fprintf,
  297:                    X86_DUMP_FPU);
  298: #else
  299:     cpu_dump_state(env, NULL, monitor_fprintf,
  300:                    0);
  301: #endif
  302: }
  303: 
  304: static void do_info_cpus(void)
  305: {
  306:     CPUState *env;
  307: 
  308:     /* just to set the default cpu if not already done */
  309:     mon_get_cpu();
  310: 
  311:     for(env = first_cpu; env != NULL; env = env->next_cpu) {
  312:         term_printf("%c CPU #%d:",
  313:                     (env == mon_cpu) ? '*' : ' ',
  314:                     env->cpu_index);
  315: #if defined(TARGET_I386)
  316:         term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base);
  317:         if (env->hflags & HF_HALTED_MASK)
  318:             term_printf(" (halted)");
  319: #elif defined(TARGET_PPC)
  320:         term_printf(" nip=0x" TARGET_FMT_lx, env->nip);
  321:         if (env->halted)
  322:             term_printf(" (halted)");
  323: #elif defined(TARGET_SPARC)
  324:         term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc);
  325:         if (env->halted)
  326:             term_printf(" (halted)");
  327: #elif defined(TARGET_MIPS)
  328:         term_printf(" PC=0x" TARGET_FMT_lx, env->PC[env->current_tc]);
  329:         if (env->halted)
  330:             term_printf(" (halted)");
  331: #endif
  332:         term_printf("\n");
  333:     }
  334: }
  335: 
  336: static void do_cpu_set(int index)
  337: {
  338:     if (mon_set_cpu(index) < 0)
  339:         term_printf("Invalid CPU index\n");
  340: }
  341: 
  342: static void do_info_jit(void)
  343: {
  344:     dump_exec_info(NULL, monitor_fprintf);
  345: }
  346: 
  347: static void do_info_history (void)
  348: {
  349:     int i;
  350:     const char *str;
  351: 
  352:     i = 0;
  353:     for(;;) {
  354:         str = readline_get_history(i);
  355:         if (!str)
  356:             break;
  357:         term_printf("%d: '%s'\n", i, str);
  358:         i++;
  359:     }
  360: }
  361: 
  362: #if defined(TARGET_PPC)
  363: /* XXX: not implemented in other targets */
  364: static void do_info_cpu_stats (void)
  365: {
  366:     CPUState *env;
  367: 
  368:     env = mon_get_cpu();
  369:     cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
  370: }
  371: #endif
  372: 
  373: static void do_quit(void)
  374: {
  375:     exit(0);
  376: }
  377: 
  378: static int eject_device(BlockDriverState *bs, int force)
  379: {
  380:     if (bdrv_is_inserted(bs)) {
  381:         if (!force) {
  382:             if (!bdrv_is_removable(bs)) {
  383:                 term_printf("device is not removable\n");
  384:                 return -1;
  385:             }
  386:             if (bdrv_is_locked(bs)) {
  387:                 term_printf("device is locked\n");
  388:                 return -1;
  389:             }
  390:         }
  391:         bdrv_close(bs);
  392:     }
  393:     return 0;
  394: }
  395: 
  396: static void do_eject(int force, const char *filename)
  397: {
  398:     BlockDriverState *bs;
  399: 
  400:     bs = bdrv_find(filename);
  401:     if (!bs) {
  402:         term_printf("device not found\n");
  403:         return;
  404:     }
  405:     eject_device(bs, force);
  406: }
  407: 
  408: static void do_change_block(const char *device, const char *filename)
  409: {
  410:     BlockDriverState *bs;
  411: 
  412:     bs = bdrv_find(device);
  413:     if (!bs) {
  414:         term_printf("device not found\n");
  415:         return;
  416:     }
  417:     if (eject_device(bs, 0) < 0)
  418:         return;
  419:     bdrv_open(bs, filename, 0);
  420:     qemu_key_check(bs, filename);
  421: }
  422: 
  423: static void do_change_vnc(const char *target)
  424: {
  425:     if (strcmp(target, "passwd") == 0 ||
  426:         strcmp(target, "password") == 0) {
  427:         char password[9];
  428:         monitor_readline("Password: ", 1, password, sizeof(password)-1);
  429:         password[sizeof(password)-1] = '\0';
  430:         if (vnc_display_password(NULL, password) < 0)
  431:             term_printf("could not set VNC server password\n");
  432:     } else {
  433:         if (vnc_display_open(NULL, target) < 0)
  434:             term_printf("could not start VNC server on %s\n", target);
  435:     }
  436: }
  437: 
  438: static void do_change(const char *device, const char *target)
  439: {
  440:     if (strcmp(device, "vnc") == 0) {
  441:         do_change_vnc(target);
  442:     } else {
  443:         do_change_block(device, target);
  444:     }
  445: }
  446: 
  447: static void do_screen_dump(const char *filename)
  448: {
  449:     vga_hw_screen_dump(filename);
  450: }
  451: 
  452: static void do_logfile(const char *filename)
  453: {
  454:     cpu_set_log_filename(filename);
  455: }
  456: 
  457: static void do_log(const char *items)
  458: {
  459:     int mask;
  460: 
  461:     if (!strcmp(items, "none")) {
  462:         mask = 0;
  463:     } else {
  464:         mask = cpu_str_to_log_mask(items);
  465:         if (!mask) {
  466:             help_cmd("log");
  467:             return;
  468:         }
  469:     }
  470:     cpu_set_log(mask);
  471: }
  472: 
  473: static void do_stop(void)
  474: {
  475:     vm_stop(EXCP_INTERRUPT);
  476: }
  477: 
  478: static void do_cont(void)
  479: {
  480:     vm_start();
  481: }
  482: 
  483: #ifdef CONFIG_GDBSTUB
  484: static void do_gdbserver(const char *port)
  485: {
  486:     if (!port)
  487:         port = DEFAULT_GDBSTUB_PORT;
  488:     if (gdbserver_start(port) < 0) {
  489:         qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
  490:     } else {
  491:         qemu_printf("Waiting gdb connection on port '%s'\n", port);
  492:     }
  493: }
  494: #endif
  495: 
  496: static void term_printc(int c)
  497: {
  498:     term_printf("'");
  499:     switch(c) {
  500:     case '\'':
  501:         term_printf("\\'");
  502:         break;
  503:     case '\\':
  504:         term_printf("\\\\");
  505:         break;
  506:     case '\n':
  507:         term_printf("\\n");
  508:         break;
  509:     case '\r':
  510:         term_printf("\\r");
  511:         break;
  512:     default:
  513:         if (c >= 32 && c <= 126) {
  514:             term_printf("%c", c);
  515:         } else {
  516:             term_printf("\\x%02x", c);
  517:         }
  518:         break;
  519:     }
  520:     term_printf("'");
  521: }
  522: 
  523: static void memory_dump(int count, int format, int wsize,
  524:                         target_phys_addr_t addr, int is_physical)
  525: {
  526:     CPUState *env;
  527:     int nb_per_line, l, line_size, i, max_digits, len;
  528:     uint8_t buf[16];
  529:     uint64_t v;
  530: 
  531:     if (format == 'i') {
  532:         int flags;
  533:         flags = 0;
  534:         env = mon_get_cpu();
  535:         if (!env && !is_physical)
  536:             return;
  537: #ifdef TARGET_I386
  538:         if (wsize == 2) {
  539:             flags = 1;
  540:         } else if (wsize == 4) {
  541:             flags = 0;
  542:         } else {
  543:             /* as default we use the current CS size */
  544:             flags = 0;
  545:             if (env) {
  546: #ifdef TARGET_X86_64
  547:                 if ((env->efer & MSR_EFER_LMA) &&
  548:                     (env->segs[R_CS].flags & DESC_L_MASK))
  549:                     flags = 2;
  550:                 else
  551: #endif
  552:                 if (!(env->segs[R_CS].flags & DESC_B_MASK))
  553:                     flags = 1;
  554:             }
  555:         }
  556: #endif
  557:         monitor_disas(env, addr, count, is_physical, flags);
  558:         return;
  559:     }
  560: 
  561:     len = wsize * count;
  562:     if (wsize == 1)
  563:         line_size = 8;
  564:     else
  565:         line_size = 16;
  566:     nb_per_line = line_size / wsize;
  567:     max_digits = 0;
  568: 
  569:     switch(format) {
  570:     case 'o':
  571:         max_digits = (wsize * 8 + 2) / 3;
  572:         break;
  573:     default:
  574:     case 'x':
  575:         max_digits = (wsize * 8) / 4;
  576:         break;
  577:     case 'u':
  578:     case 'd':
  579:         max_digits = (wsize * 8 * 10 + 32) / 33;
  580:         break;
  581:     case 'c':
  582:         wsize = 1;
  583:         break;
  584:     }
  585: 
  586:     while (len > 0) {
  587:         if (is_physical)
  588:             term_printf(TARGET_FMT_plx ":", addr);
  589:         else
  590:             term_printf(TARGET_FMT_lx ":", (target_ulong)addr);
  591:         l = len;
  592:         if (l > line_size)
  593:             l = line_size;
  594:         if (is_physical) {
  595:             cpu_physical_memory_rw(addr, buf, l, 0);
  596:         } else {
  597:             env = mon_get_cpu();
  598:             if (!env)
  599:                 break;
  600:             cpu_memory_rw_debug(env, addr, buf, l, 0);
  601:         }
  602:         i = 0;
  603:         while (i < l) {
  604:             switch(wsize) {
  605:             default:
  606:             case 1:
  607:                 v = ldub_raw(buf + i);
  608:                 break;
  609:             case 2:
  610:                 v = lduw_raw(buf + i);
  611:                 break;
  612:             case 4:
  613:                 v = (uint32_t)ldl_raw(buf + i);
  614:                 break;
  615:             case 8:
  616:                 v = ldq_raw(buf + i);
  617:                 break;
  618:             }
  619:             term_printf(" ");
  620:             switch(format) {
  621:             case 'o':
  622:                 term_printf("%#*" PRIo64, max_digits, v);
  623:                 break;
  624: