The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_command.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: db_command.c,v 1.91 2006/11/16 01:32:44 christos Exp $ */
    2 
    3 /*
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 /*
   30  * Command dispatcher.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.91 2006/11/16 01:32:44 christos Exp $");
   35 
   36 #include "opt_ddb.h"
   37 #include "opt_kgdb.h"
   38 #include "opt_inet.h"
   39 #include "opt_ddbparam.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/reboot.h>
   44 #include <sys/device.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mbuf.h>
   47 #include <sys/namei.h>
   48 #include <sys/pool.h>
   49 #include <sys/proc.h>
   50 #include <sys/vnode.h>
   51 
   52 #include <machine/db_machdep.h>         /* type definitions */
   53 
   54 #if defined(_KERNEL_OPT)
   55 #include "opt_multiprocessor.h"
   56 #endif
   57 #ifdef MULTIPROCESSOR
   58 #include <machine/cpu.h>
   59 #endif
   60 
   61 #include <ddb/db_lex.h>
   62 #include <ddb/db_output.h>
   63 #include <ddb/db_command.h>
   64 #include <ddb/db_break.h>
   65 #include <ddb/db_watch.h>
   66 #include <ddb/db_run.h>
   67 #include <ddb/db_variables.h>
   68 #include <ddb/db_interface.h>
   69 #include <ddb/db_sym.h>
   70 #include <ddb/db_extern.h>
   71 
   72 #include <uvm/uvm_extern.h>
   73 #include <uvm/uvm_ddb.h>
   74 
   75 #include "arp.h"
   76 
   77 /*
   78  * Results of command search.
   79  */
   80 #define CMD_UNIQUE      0
   81 #define CMD_FOUND       1
   82 #define CMD_NONE        2
   83 #define CMD_AMBIGUOUS   3
   84 #define CMD_HELP        4
   85 
   86 /*
   87  * Exported global variables
   88  */
   89 boolean_t       db_cmd_loop_done;
   90 label_t         *db_recover;
   91 db_addr_t       db_dot;
   92 db_addr_t       db_last_addr;
   93 db_addr_t       db_prev;
   94 db_addr_t       db_next;
   95 
   96 /*
   97  * if 'ed' style: 'dot' is set at start of last item printed,
   98  * and '+' points to next line.
   99  * Otherwise: 'dot' points to next item, '..' points to last.
  100  */
  101 static boolean_t db_ed_style = TRUE;
  102 
  103 static void     db_buf_print_cmd(db_expr_t, int, db_expr_t, const char *);
  104 static void     db_cmd_list(const struct db_command *);
  105 static int      db_cmd_search(const char *, const struct db_command *,
  106                     const struct db_command **);
  107 static void     db_command(const struct db_command **,
  108                     const struct db_command *);
  109 static void     db_event_print_cmd(db_expr_t, int, db_expr_t, const char *);
  110 static void     db_fncall(db_expr_t, int, db_expr_t, const char *);
  111 static void     db_malloc_print_cmd(db_expr_t, int, db_expr_t, const char *);
  112 static void     db_map_print_cmd(db_expr_t, int, db_expr_t, const char *);
  113 static void     db_namecache_print_cmd(db_expr_t, int, db_expr_t, const char *);
  114 static void     db_object_print_cmd(db_expr_t, int, db_expr_t, const char *);
  115 static void     db_page_print_cmd(db_expr_t, int, db_expr_t, const char *);
  116 static void     db_show_all_pages(db_expr_t, int, db_expr_t, const char *);
  117 static void     db_pool_print_cmd(db_expr_t, int, db_expr_t, const char *);
  118 static void     db_reboot_cmd(db_expr_t, int, db_expr_t, const char *);
  119 static void     db_sifting_cmd(db_expr_t, int, db_expr_t, const char *);
  120 static void     db_stack_trace_cmd(db_expr_t, int, db_expr_t, const char *);
  121 static void     db_sync_cmd(db_expr_t, int, db_expr_t, const char *);
  122 static void     db_uvmexp_print_cmd(db_expr_t, int, db_expr_t, const char *);
  123 static void     db_vnode_print_cmd(db_expr_t, int, db_expr_t, const char *);
  124 static void     db_mount_print_cmd(db_expr_t, int, db_expr_t, const char *);
  125 static void     db_mbuf_print_cmd(db_expr_t, int, db_expr_t, const char *);
  126 
  127 /*
  128  * 'show' commands
  129  */
  130 
  131 static const struct db_command db_show_all_cmds[] = {
  132         { "callout",    db_show_callout,        0, NULL },
  133         { "pages",      db_show_all_pages,      0, NULL },
  134         { "procs",      db_show_all_procs,      0, NULL },
  135         { "pools",      db_show_all_pools,      0, NULL },
  136         { NULL,         NULL,                   0, NULL }
  137 };
  138 
  139 static const struct db_command db_show_cmds[] = {
  140         { "all",        NULL,                   0,      db_show_all_cmds },
  141 #if defined(INET) && (NARP > 0)
  142         { "arptab",     db_show_arptab,         0,      NULL },
  143 #endif
  144         { "breaks",     db_listbreak_cmd,       0,      NULL },
  145         { "buf",        db_buf_print_cmd,       0,      NULL },
  146         { "event",      db_event_print_cmd,     0,      NULL },
  147         { "malloc",     db_malloc_print_cmd,    0,      NULL },
  148         { "map",        db_map_print_cmd,       0,      NULL },
  149         { "mount",      db_mount_print_cmd,     0,      NULL },
  150         { "mbuf",       db_mbuf_print_cmd,      0,      NULL },
  151         { "ncache",     db_namecache_print_cmd, 0,      NULL },
  152         { "object",     db_object_print_cmd,    0,      NULL },
  153         { "page",       db_page_print_cmd,      0,      NULL },
  154         { "pool",       db_pool_print_cmd,      0,      NULL },
  155         { "registers",  db_show_regs,           0,      NULL },
  156         { "sched_qs",   db_show_sched_qs,       0,      NULL },
  157         { "uvmexp",     db_uvmexp_print_cmd,    0,      NULL },
  158         { "vnode",      db_vnode_print_cmd,     0,      NULL },
  159         { "watches",    db_listwatch_cmd,       0,      NULL },
  160         { NULL,         NULL,                   0,      NULL }
  161 };
  162 
  163 /* arch/<arch>/<arch>/db_interface.c */
  164 #ifdef DB_MACHINE_COMMANDS
  165 extern const struct db_command db_machine_command_table[];
  166 #endif
  167 
  168 static const struct db_command db_command_table[] = {
  169         { "b",          db_breakpoint_cmd,      0,              NULL },
  170         { "break",      db_breakpoint_cmd,      0,              NULL },
  171         { "bt",         db_stack_trace_cmd,     0,              NULL },
  172         { "c",          db_continue_cmd,        0,              NULL },
  173         { "call",       db_fncall,              CS_OWN,         NULL },
  174         { "callout",    db_show_callout,        0,              NULL },
  175         { "continue",   db_continue_cmd,        0,              NULL },
  176         { "d",          db_delete_cmd,          0,              NULL },
  177         { "delete",     db_delete_cmd,          0,              NULL },
  178         { "dmesg",      db_dmesg,               0,              NULL },
  179         { "dwatch",     db_deletewatch_cmd,     0,              NULL },
  180         { "examine",    db_examine_cmd,         CS_SET_DOT,     NULL },
  181         { "kill",       db_kill_proc,           CS_OWN,         NULL },
  182 #ifdef KGDB
  183         { "kgdb",       db_kgdb_cmd,            0,              NULL },
  184 #endif
  185 #ifdef DB_MACHINE_COMMANDS
  186         { "machine",    NULL,                   0, db_machine_command_table },
  187 #endif
  188         { "match",      db_trace_until_matching_cmd,0,          NULL },
  189         { "next",       db_trace_until_matching_cmd,0,          NULL },
  190         { "p",          db_print_cmd,           0,              NULL },
  191         { "print",      db_print_cmd,           0,              NULL },
  192         { "ps",         db_show_all_procs,      0,              NULL },
  193         { "reboot",     db_reboot_cmd,          CS_OWN,         NULL },
  194         { "s",          db_single_step_cmd,     0,              NULL },
  195         { "search",     db_search_cmd,          CS_OWN|CS_SET_DOT, NULL },
  196         { "set",        db_set_cmd,             CS_OWN,         NULL },
  197         { "show",       NULL,                   0,              db_show_cmds },
  198         { "sifting",    db_sifting_cmd,         CS_OWN,         NULL },
  199         { "step",       db_single_step_cmd,     0,              NULL },
  200         { "sync",       db_sync_cmd,            CS_OWN,         NULL },
  201         { "trace",      db_stack_trace_cmd,     0,              NULL },
  202         { "until",      db_trace_until_call_cmd,0,              NULL },
  203         { "w",          db_write_cmd,           CS_MORE|CS_SET_DOT, NULL },
  204         { "watch",      db_watchpoint_cmd,      CS_MORE,        NULL },
  205         { "write",      db_write_cmd,           CS_MORE|CS_SET_DOT, NULL },
  206         { "x",          db_examine_cmd,         CS_SET_DOT,     NULL },
  207         { NULL,         NULL,                   0,              NULL }
  208 };
  209 
  210 static const struct db_command  *db_last_command = NULL;
  211 #if defined(DDB_COMMANDONENTER)
  212 char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
  213 #else /* defined(DDB_COMMANDONENTER) */
  214 char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
  215 #endif /* defined(DDB_COMMANDONENTER) */
  216 #define DB_LINE_SEP     ';'
  217 
  218 /*
  219  * Utility routine - discard tokens through end-of-line.
  220  */
  221 void
  222 db_skip_to_eol(void)
  223 {
  224         int t;
  225 
  226         do {
  227                 t = db_read_token();
  228         } while (t != tEOL);
  229 }
  230 
  231 void
  232 db_error(const char *s)
  233 {
  234 
  235         if (s)
  236                 db_printf("%s", s);
  237         db_flush_lex();
  238         longjmp(db_recover);
  239 }
  240 
  241 static void
  242 db_execute_commandlist(const char *cmdlist)
  243 {
  244         const char *cmd = cmdlist;
  245         const struct db_command *dummy = NULL;
  246 
  247         while (*cmd != '\0') {
  248                 const char *ep = cmd;
  249 
  250                 while (*ep != '\0' && *ep != DB_LINE_SEP) {
  251                         ep++;
  252                 }
  253                 db_set_line(cmd, ep);
  254                 db_command(&dummy, db_command_table);
  255                 cmd = ep;
  256                 if (*cmd == DB_LINE_SEP) {
  257                         cmd++;
  258                 }
  259         }
  260 }
  261 
  262 void
  263 db_command_loop(void)
  264 {
  265         label_t db_jmpbuf;
  266         label_t *savejmp;
  267 
  268         /*
  269          * Initialize 'prev' and 'next' to dot.
  270          */
  271         db_prev = db_dot;
  272         db_next = db_dot;
  273 
  274         db_cmd_loop_done = 0;
  275 
  276         savejmp = db_recover;
  277         db_recover = &db_jmpbuf;
  278         (void) setjmp(&db_jmpbuf);
  279 
  280         db_execute_commandlist(db_cmd_on_enter);
  281 
  282         while (!db_cmd_loop_done) {
  283                 if (db_print_position() != 0)
  284                         db_printf("\n");
  285                 db_output_line = 0;
  286 
  287 
  288 #ifdef MULTIPROCESSOR
  289                 db_printf("db{%ld}> ", (long)cpu_number());
  290 #else
  291                 db_printf("db> ");
  292 #endif
  293                 (void) db_read_line();
  294 
  295                 db_command(&db_last_command, db_command_table);
  296         }
  297 
  298         db_recover = savejmp;
  299 }
  300 
  301 /*
  302  * Search for command prefix.
  303  */
  304 static int
  305 db_cmd_search(const char *name, const struct db_command *table,
  306     const struct db_command **cmdp)
  307 {
  308         const struct db_command *cmd;
  309         int                     result = CMD_NONE;
  310 
  311         for (cmd = table; cmd->name != 0; cmd++) {
  312                 const char *lp;
  313                 const char *rp;
  314                 int  c;
  315 
  316                 lp = name;
  317                 rp = cmd->name;
  318                 while ((c = *lp) == *rp) {
  319                         if (c == 0) {
  320                                 /* complete match */
  321                                 *cmdp = cmd;
  322                                 return (CMD_UNIQUE);
  323                         }
  324                         lp++;
  325                         rp++;
  326                 }
  327                 if (c == 0) {
  328                         /* end of name, not end of command -
  329                            partial match */
  330                         if (result == CMD_FOUND) {
  331                                 result = CMD_AMBIGUOUS;
  332                                 /* but keep looking for a full match -
  333                                    this lets us match single letters */
  334                         } else {
  335                                 *cmdp = cmd;
  336                                 result = CMD_FOUND;
  337                         }
  338                 }
  339         }
  340         if (result == CMD_NONE) {
  341                 /* check for 'help' */
  342                 if (name[0] == 'h' && name[1] == 'e'
  343                     && name[2] == 'l' && name[3] == 'p')
  344                         result = CMD_HELP;
  345         }
  346         return (result);
  347 }
  348 
  349 static void
  350 db_cmd_list(const struct db_command *table)
  351 {
  352         int      i, j, w, columns, lines, width=0, numcmds;
  353         const char      *p;
  354 
  355         for (numcmds = 0; table[numcmds].name != NULL; numcmds++) {
  356                 w = strlen(table[numcmds].name);
  357                 if (w > width)
  358                         width = w;
  359         }
  360         width = DB_NEXT_TAB(width);
  361 
  362         columns = db_max_width / width;
  363         if (columns == 0)
  364                 columns = 1;
  365         lines = (numcmds + columns - 1) / columns;
  366         for (i = 0; i < lines; i++) {
  367                 for (j = 0; j < columns; j++) {
  368                         p = table[j * lines + i].name;
  369                         if (p)
  370                                 db_printf("%s", p);
  371                         if (j * lines + i + lines >= numcmds) {
  372                                 db_putchar('\n');
  373                                 break;
  374                         }
  375                         if (p) {
  376                                 w = strlen(p);
  377                                 while (w < width) {
  378                                         w = DB_NEXT_TAB(w);
  379                                         db_putchar('\t');
  380                                 }
  381                         }
  382                 }
  383         }
  384 }
  385 
  386 static void
  387 db_command(const struct db_command **last_cmdp,
  388     const struct db_command *cmd_table)
  389 {
  390         const struct db_command *cmd;
  391         int             t;
  392         char            modif[TOK_STRING_SIZE];
  393         db_expr_t       addr, count;
  394         boolean_t       have_addr = FALSE;
  395         int             result;
  396         static db_expr_t last_count = 0;
  397 
  398         cmd = NULL;     /* XXX gcc */
  399 
  400         t = db_read_token();
  401         if ((t == tEOL) || (t == tCOMMA)) {
  402                 /*
  403                  * An empty line repeats last command, at 'next'.
  404                  * Only a count repeats the last command with the new count.
  405                  */
  406                 cmd = *last_cmdp;
  407                 addr = (db_expr_t)db_next;
  408                 if (t == tCOMMA) {
  409                         if (!db_expression(&count)) {
  410                                 db_printf("Count missing\n");
  411                                 db_flush_lex();
  412                                 return;
  413                         }
  414                 } else
  415                         count = last_count;
  416                 have_addr = FALSE;
  417                 modif[0] = '\0';
  418                 db_skip_to_eol();
  419         } else if (t == tEXCL) {
  420                 db_fncall(0, 0, 0, NULL);
  421                 return;
  422         } else if (t != tIDENT) {
  423                 db_printf("?\n");
  424                 db_flush_lex();
  425                 return;
  426         } else {
  427                 /*
  428                  * Search for command
  429                  */
  430                 while (cmd_table) {
  431                         result = db_cmd_search(db_tok_string, cmd_table, &cmd);
  432                         switch (result) {
  433                         case CMD_NONE:
  434                                 db_printf("No such command\n");
  435                                 db_flush_lex();
  436                                 return;
  437                         case CMD_AMBIGUOUS:
  438                                 db_printf("Ambiguous\n");
  439                                 db_flush_lex();
  440                                 return;
  441                         case CMD_HELP:
  442                                 db_cmd_list(cmd_table);
  443                                 db_flush_lex();
  444                                 return;
  445                         default:
  446                                 break;
  447                         }
  448                         if ((cmd_table = cmd->more) != 0) {
  449                                 t = db_read_token();
  450                                 if (t != tIDENT) {
  451                                         db_cmd_list(cmd_table);
  452                                         db_flush_lex();
  453                                         return;
  454                                 }
  455                         }
  456                 }
  457 
  458                 if ((cmd->flag & CS_OWN) == 0) {
  459                         /*
  460                          * Standard syntax:
  461                          * command [/modifier] [addr] [,count]
  462                          */
  463                         t = db_read_token();
  464                         if (t == tSLASH) {
  465                                 t = db_read_token();
  466                                 if (t != tIDENT) {
  467                                         db_printf("Bad modifier\n");
  468                                         db_flush_lex();
  469                                         return;
  470                                 }
  471                                 strlcpy(modif, db_tok_string, sizeof(modif));
  472                         } else {
  473                                 db_unread_token(t);
  474                                 modif[0] = '\0';
  475                         }
  476 
  477                         if (db_expression(&addr)) {
  478                                 db_dot = (db_addr_t) addr;
  479                                 db_last_addr = db_dot;
  480                                 have_addr = TRUE;
  481                         } else {
  482                                 addr = (db_expr_t) db_dot;
  483                                 have_addr = FALSE;
  484                         }
  485                         t = db_read_token();
  486                         if (t == tCOMMA) {
  487                                 if (!db_expression(&count)) {
  488                                         db_printf("Count missing\n");
  489                                         db_flush_lex();
  490                                         return;
  491                                 }
  492                         } else {
  493                                 db_unread_token(t);
  494                                 count = -1;
  495                         }
  496                         if ((cmd->flag & CS_MORE) == 0) {
  497                                 db_skip_to_eol();
  498                         }
  499                 }
  500         }
  501         *last_cmdp = cmd;
  502         last_count = count;
  503         if (cmd != 0) {
  504                 /*
  505                  * Execute the command.
  506                  */
  507                 (*cmd->fcn)(addr, have_addr, count, modif);
  508 
  509                 if (cmd->flag & CS_SET_DOT) {
  510                         /*
  511                          * If command changes dot, set dot to
  512                          * previous address displayed (if 'ed' style).
  513                          */
  514                         if (db_ed_style)
  515                                 db_dot = db_prev;
  516                         else
  517                                 db_dot = db_next;
  518                 } else {
  519                         /*
  520                          * If command does not change dot,
  521                          * set 'next' location to be the same.
  522                          */
  523                         db_next = db_dot;
  524                 }
  525         }
  526 }
  527 
  528 /*ARGSUSED*/
  529 static void
  530 db_map_print_cmd(db_expr_t addr, int have_addr, db_expr_t count,
  531     const char *modif)
  532 {
  533         boolean_t full = FALSE;
  534 
  535         if (modif[0] == 'f')
  536                 full = TRUE;
  537 
  538         if (have_addr == FALSE)
  539                 addr = (db_expr_t)(intptr_t) kernel_map;
  540 
  541         uvm_map_printit((struct vm_map *)(intptr_t) addr, full, db_printf);
  542 }
  543 
  544 /*ARGSUSED*/
  545 static void
  546 db_malloc_print_cmd(db_expr_t addr, int have_addr,
  547     db_expr_t count, const char *modif)
  548 {
  549 
  550 #ifdef MALLOC_DEBUG
  551         if (!have_addr)
  552                 addr = 0;
  553 
  554         debug_malloc_printit(db_printf, (vaddr_t) addr);
  555 #else
  556         db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
  557 #endif /* MALLOC_DEBUG */
  558 }
  559 
  560 /*ARGSUSED*/
  561 static void
  562 db_object_print_cmd(db_expr_t addr, int have_addr,
  563     db_expr_t count, const char *modif)
  564 {
  565         boolean_t full = FALSE;
  566 
  567         if (modif[0] == 'f')
  568                 full = TRUE;
  569 
  570         uvm_object_printit((struct uvm_object *)(intptr_t) addr, full,
  571             db_printf);
  572 }
  573 
  574 /*ARGSUSED*/
  575 static void
  576 db_page_print_cmd(db_expr_t addr, int have_addr,
  577     db_expr_t count, const char *modif)
  578 {
  579         boolean_t full = FALSE;
  580 
  581         if (modif[0] == 'f')
  582                 full = TRUE;
  583 
  584         uvm_page_printit((struct vm_page *)(intptr_t) addr, full, db_printf);
  585 }
  586 
  587 /*ARGSUSED*/
  588 static void
  589 db_show_all_pages(db_expr_t addr, int have_addr,
  590     db_expr_t count, const char *modif)
  591 {
  592 
  593         uvm_page_printall(db_printf);
  594 }
  595 
  596 /*ARGSUSED*/
  597 static void
  598 db_buf_print_cmd(db_expr_t addr, int have_addr,
  599     db_expr_t count, const char *modif)
  600 {
  601         boolean_t full = FALSE;
  602 
  603         if (modif[0] == 'f')
  604                 full = TRUE;
  605 
  606         vfs_buf_print((struct buf *)(intptr_t) addr, full, db_printf);
  607 }
  608 
  609 /*ARGSUSED*/
  610 static void
  611 db_event_print_cmd(db_expr_t addr, int have_addr,
  612     db_expr_t count, const char *modif)
  613 {
  614         boolean_t full = FALSE;
  615 
  616         if (modif[0] == 'f')
  617                 full = TRUE;
  618 
  619         event_print(full, db_printf);
  620 }
  621 
  622 /*ARGSUSED*/
  623 static void
  624 db_vnode_print_cmd(db_expr_t addr, int have_addr,
  625     db_expr_t count, const char *modif)
  626 {
  627         boolean_t full = FALSE;
  628 
  629         if (modif[0] == 'f')
  630                 full = TRUE;
  631 
  632         vfs_vnode_print((struct vnode *)(intptr_t) addr, full, db_printf);
  633 }
  634 
  635 static void
  636 db_mount_print_cmd(db_expr_t addr, int have_addr,
  637     db_expr_t count, const char *modif)
  638 {
  639         boolean_t full = FALSE;
  640 
  641         if (modif[0] == 'f')
  642                 full = TRUE;
  643 
  644         vfs_mount_print((struct mount *)(intptr_t) addr, full, db_printf);
  645 }
  646 
  647 /*ARGSUSED*/
  648 static void
  649 db_mbuf_print_cmd(db_expr_t addr, int have_addr,
  650     db_expr_t count, const char *modif)
  651 {
  652 
  653         m_print((const struct mbuf *)(intptr_t) addr, modif, db_printf);
  654 }
  655 
  656 /*ARGSUSED*/
  657 static void
  658 db_pool_print_cmd(db_expr_t addr, int have_addr,
  659     db_expr_t count, const char *modif)
  660 {
  661 
  662         pool_printit((struct pool *)(intptr_t) addr, modif, db_printf);
  663 }
  664 
  665 /*ARGSUSED*/
  666 static void
  667 db_namecache_print_cmd(db_expr_t addr, int have_addr,
  668     db_expr_t count, const char *modif)
  669 {
  670 
  671         namecache_print((struct vnode *)(intptr_t) addr, db_printf);
  672 }
  673 
  674 /*ARGSUSED*/
  675 static void
  676 db_uvmexp_print_cmd(db_expr_t addr, int have_addr,
  677     db_expr_t count, const char *modif)
  678 {
  679 
  680         uvmexp_print(db_printf);
  681 }
  682 
  683 /*
  684  * Call random function:
  685  * !expr(arg,arg,arg)
  686  */
  687 /*ARGSUSED*/
  688 static void
  689 db_fncall(db_expr_t addr, int have_addr,
  690     db_expr_t count, const char *modif)
  691 {
  692         db_expr_t       fn_addr;
  693 #define MAXARGS         11
  694         db_expr_t       args[MAXARGS];
  695         int             nargs = 0;
  696         db_expr_t       retval;
  697         db_expr_t       (*func)(db_expr_t, ...);
  698         int             t;
  699 
  700         if (!db_expression(&fn_addr)) {
  701                 db_printf("Bad function\n");
  702                 db_flush_lex();
  703                 return;
  704         }
  705         func = (db_expr_t (*)(db_expr_t, ...))(intptr_t) fn_addr;
  706 
  707         t = db_read_token();
  708         if (t == tLPAREN) {
  709                 if (db_expression(&args[0])) {
  710                         nargs++;
  711                         while ((t = db_read_token()) == tCOMMA) {
  712                                 if (nargs == MAXARGS) {
  713                                         db_printf("Too many arguments\n");
  714                                         db_flush_lex();
  715                                         return;
  716                                 }
  717                                 if (!db_expression(&args[nargs])) {
  718                                         db_printf("Argument missing\n");
  719                                         db_flush_lex();
  720                                         return;
  721                                 }
  722                                 nargs++;
  723                         }
  724                         db_unread_token(t);
  725                 }
  726                 if (db_read_token() != tRPAREN) {
  727                         db_printf("?\n");
  728                         db_flush_lex();
  729                         return;
  730                 }
  731         }
  732         db_skip_to_eol();
  733 
  734         while (nargs < MAXARGS) {
  735                 args[nargs++] = 0;
  736         }
  737 
  738         retval = (*func)(args[0], args[1], args[2], args[3], args[4],
  739                          args[5], args[6], args[7], args[8], args[9]);
  740         db_printf("%s\n", db_num_to_str(retval));
  741 }
  742 
  743 static void
  744 db_reboot_cmd(db_expr_t addr, int have_addr,
  745     db_expr_t count, const char *modif)
  746 {
  747         db_expr_t bootflags;
  748 
  749         /* Flags, default to RB_AUTOBOOT */
  750         if (!db_expression(&bootflags))
  751                 bootflags = (db_expr_t)RB_AUTOBOOT;
  752         if (db_read_token() != tEOL) {
  753                 db_error("?\n");
  754                 /*NOTREACHED*/
  755         }
  756         /*
  757          * We are leaving DDB, never to return upward.
  758          * Clear db_recover so that we can debug faults in functions
  759          * called from cpu_reboot.
  760          */
  761         db_recover = 0;
  762         cpu_reboot((int)bootflags, NULL);
  763 }
  764 
  765 static void
  766 db_sifting_cmd(db_expr_t addr, int have_addr,
  767     db_expr_t count, const char *modif)
  768 {
  769         int     mode, t;
  770 
  771         t = db_read_token();
  772         if (t == tSLASH) {
  773                 t = db_read_token();
  774                 if (t != tIDENT) {
  775                         bad_modifier:
  776                         db_printf("Bad modifier\n");
  777                         db_flush_lex();
  778                         return;
  779                 }
  780                 if (!strcmp(db_tok_string, "F"))
  781                         mode = 'F';
  782                 else
  783                         goto bad_modifier;
  784                 t = db_read_token();
  785         } else
  786                 mode = 0;
  787 
  788         if (t == tIDENT)
  789                 db_sifting(db_tok_string, mode);
  790         else {
  791                 db_printf("Bad argument (non-string)\n");
  792                 db_flush_lex();
  793         }
  794 }
  795 
  796 static void
  797 db_stack_trace_cmd(db_expr_t addr, int have_addr, db_expr_t count, const char *modif)
  798 {
  799         register const char *cp = modif;
  800         register char c;
  801         void (*pr)(const char *, ...);
  802 
  803         pr = db_printf;
  804         while ((c = *cp++) != 0)
  805                 if (c == 'l')
  806                         pr = printf;
  807 
  808         if (count == -1)
  809                 count = 65535;
  810 
  811         db_stack_trace_print(addr, have_addr, count, modif, pr);
  812 }
  813 
  814 static void
  815 db_sync_cmd(db_expr_t addr, int have_addr,
  816     db_expr_t count, const char *modif)
  817 {
  818 
  819         /*
  820          * We are leaving DDB, never to return upward.
  821          * Clear db_recover so that we can debug faults in functions
  822          * called from cpu_reboot.
  823          */
  824         db_recover = 0;
  825         cpu_reboot(RB_DUMP, NULL);
  826 }

Cache object: fae55bae69deedd585e34d9ea74b2826


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.