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.120.4.2 2009/01/09 03:32:01 snj Exp $ */
    2 /*
    3  * Mach Operating System
    4  * Copyright (c) 1991,1990 Carnegie Mellon University
    5  * All Rights Reserved.
    6  *
    7  * Permission to use, copy, modify and distribute this software and its
    8  * documentation is hereby granted, provided that both the copyright
    9  * notice and this permission notice appear in all copies of the
   10  * software, derivative works or modified versions, and any portions
   11  * thereof, and that both notices appear in supporting documentation.
   12  *
   13  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   14  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   15  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   16  *
   17  * Carnegie Mellon requests users of this software to return to
   18  *
   19  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   20  *  School of Computer Science
   21  *  Carnegie Mellon University
   22  *  Pittsburgh PA 15213-3890
   23  *
   24  * any improvements or extensions that they make and grant Carnegie the
   25  * rights to redistribute these changes.
   26  */
   27 /*
   28  * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
   29  * All rights reserved.
   30  *
   31  * This code is derived from software contributed to The NetBSD Foundation
   32  * by Adam Hamsik.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  *
   43  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   44  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   45  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   46  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   47  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   48  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   49  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   50  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   51  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   52  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   53  * POSSIBILITY OF SUCH DAMAGE.
   54  */
   55 
   56 /*
   57  * Command dispatcher.
   58  */
   59 
   60 #include <sys/cdefs.h>
   61 __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.120.4.2 2009/01/09 03:32:01 snj Exp $");
   62 
   63 #include "opt_ddb.h"
   64 #include "opt_kgdb.h"
   65 #include "opt_inet.h"
   66 #include "opt_uvmhist.h"
   67 #include "opt_ddbparam.h"
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/reboot.h>
   72 #include <sys/device.h>
   73 #include <sys/lwp.h>
   74 #include <sys/malloc.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/namei.h>
   77 #include <sys/pool.h>
   78 #include <sys/proc.h>
   79 #include <sys/vnode.h>
   80 #include <sys/vmem.h>
   81 #include <sys/lockdebug.h>
   82 #include <sys/sleepq.h>
   83 #include <sys/cpu.h>
   84 
   85 /*include queue macros*/
   86 #include <sys/queue.h>
   87 
   88 #include <machine/db_machdep.h>         /* type definitions */
   89 
   90 #if defined(_KERNEL_OPT)
   91 #include "opt_multiprocessor.h"
   92 #endif
   93 
   94 #include <ddb/db_lex.h>
   95 #include <ddb/db_output.h>
   96 #include <ddb/db_command.h>
   97 #include <ddb/db_break.h>
   98 #include <ddb/db_watch.h>
   99 #include <ddb/db_run.h>
  100 #include <ddb/db_variables.h>
  101 #include <ddb/db_interface.h>
  102 #include <ddb/db_sym.h>
  103 #include <ddb/db_extern.h>
  104 
  105 #include <uvm/uvm_extern.h>
  106 #include <uvm/uvm_ddb.h>
  107 
  108 #include "arp.h"
  109 
  110 /*
  111  * Results of command search.
  112  */
  113 #define CMD_EXACT               0
  114 #define CMD_PREFIX              1
  115 #define CMD_NONE                2
  116 #define CMD_AMBIGUOUS   3
  117 
  118 /*
  119  * Exported global variables
  120  */
  121 bool            db_cmd_loop_done;
  122 label_t         *db_recover;
  123 db_addr_t       db_dot;
  124 db_addr_t       db_last_addr;
  125 db_addr_t       db_prev;
  126 db_addr_t       db_next;
  127 
  128 
  129 /*
  130  * New DDB api for adding and removing commands uses three lists, because
  131  * we use two types of commands
  132  * a) standard commands without subcommands -> reboot
  133  * b) show commands which are subcommands of show command -> show aio_jobs
  134  * c) if defined machine specific commands
  135  *
  136  * ddb_add_cmd, ddb_rem_cmd use type (DDB_SHOW_CMD||DDB_BASE_CMD)argument to
  137  * add them to representativ lists.
  138  */
  139 
  140 static const struct db_command db_command_table[];
  141 static const struct db_command db_show_cmds[];
  142 
  143 #ifdef DB_MACHINE_COMMANDS
  144 static const struct db_command db_machine_command_table[];
  145 #endif
  146 
  147 /* the global queue of all command tables */
  148 TAILQ_HEAD(db_cmd_tbl_en_head, db_cmd_tbl_en);
  149 
  150 /* TAILQ entry used to register command tables */
  151 struct db_cmd_tbl_en {
  152         const struct db_command *db_cmd;        /* cmd table */
  153         TAILQ_ENTRY(db_cmd_tbl_en) db_cmd_next;
  154 };
  155 
  156 /* head of base commands list */
  157 static struct db_cmd_tbl_en_head db_base_cmd_list =
  158         TAILQ_HEAD_INITIALIZER(db_base_cmd_list);
  159 static struct db_cmd_tbl_en db_base_cmd_builtins =
  160      { .db_cmd = db_command_table };
  161 
  162 /* head of show commands list */
  163 static struct db_cmd_tbl_en_head db_show_cmd_list =
  164         TAILQ_HEAD_INITIALIZER(db_show_cmd_list);
  165 static struct db_cmd_tbl_en db_show_cmd_builtins =
  166      { .db_cmd = db_show_cmds };
  167 
  168 /* head of machine commands list */
  169 static struct db_cmd_tbl_en_head db_mach_cmd_list =
  170         TAILQ_HEAD_INITIALIZER(db_mach_cmd_list);
  171 #ifdef DB_MACHINE_COMMANDS
  172 static struct db_cmd_tbl_en db_mach_cmd_builtins =
  173      { .db_cmd = db_machine_command_table };
  174 #endif
  175 
  176 /*
  177  * if 'ed' style: 'dot' is set at start of last item printed,
  178  * and '+' points to next line.
  179  * Otherwise: 'dot' points to next item, '..' points to last.
  180  */
  181 static bool      db_ed_style = true;
  182 
  183 static void     db_init_commands(void);
  184 static int      db_register_tbl_entry(uint8_t type,
  185     struct db_cmd_tbl_en *list_ent);
  186 static void     db_cmd_list(const struct db_cmd_tbl_en_head *);
  187 static int      db_cmd_search(const char *, struct db_cmd_tbl_en_head *,
  188                               const struct db_command **);
  189 static int      db_cmd_search_table(const char *, const struct db_command *,
  190                                     const struct db_command **);
  191 static void     db_cmd_search_failed(char *, int);
  192 static const struct db_command *db_read_command(void);
  193 static void     db_command(const struct db_command **);
  194 static void     db_buf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  195 static void     db_event_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  196 static void     db_fncall(db_expr_t, bool, db_expr_t, const char *);
  197 static void     db_help_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  198 static void     db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  199 static void     db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  200 static void     db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  201 static void     db_malloc_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  202 static void     db_map_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  203 static void     db_namecache_print_cmd(db_expr_t, bool, db_expr_t,
  204                     const char *);
  205 static void     db_object_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  206 static void     db_page_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  207 static void     db_show_all_pages(db_expr_t, bool, db_expr_t, const char *);
  208 static void     db_pool_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  209 static void     db_reboot_cmd(db_expr_t, bool, db_expr_t, const char *);
  210 static void     db_sifting_cmd(db_expr_t, bool, db_expr_t, const char *);
  211 static void     db_stack_trace_cmd(db_expr_t, bool, db_expr_t, const char *);
  212 static void     db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
  213 static void     db_whatis_cmd(db_expr_t, bool, db_expr_t, const char *);
  214 static void     db_uvmexp_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  215 #ifdef UVMHIST
  216 static void     db_uvmhist_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  217 #endif
  218 static void     db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *);
  219 
  220 static const struct db_command db_show_cmds[] = {
  221         /*added from all sub cmds*/
  222         { DDB_ADD_CMD("callout",  db_show_callout,
  223             0 ,"List all used callout functions.",NULL,NULL) },
  224         { DDB_ADD_CMD("pages",  db_show_all_pages,
  225             0 ,"List all used memory pages.",NULL,NULL) },
  226         { DDB_ADD_CMD("procs",  db_show_all_procs,
  227             0 ,"List all processes.",NULL,NULL) },
  228         { DDB_ADD_CMD("pools",  db_show_all_pools,
  229             0 ,"Show all poolS",NULL,NULL) },
  230         /*added from all sub cmds*/
  231         { DDB_ADD_CMD("aio_jobs",       db_show_aio_jobs,       0,
  232             "Show aio jobs",NULL,NULL) },
  233         { DDB_ADD_CMD("all",    NULL,
  234             CS_COMPAT, NULL,NULL,NULL) },
  235 #if defined(INET) && (NARP > 0)
  236         { DDB_ADD_CMD("arptab", db_show_arptab,         0,NULL,NULL,NULL) },
  237 #endif
  238         { DDB_ADD_CMD("breaks", db_listbreak_cmd,       0,
  239             "Display all breaks.",NULL,NULL) },
  240         { DDB_ADD_CMD("buf",    db_buf_print_cmd,       0,
  241             "Print the struct buf at address.", "[/f] address",NULL) },
  242         { DDB_ADD_CMD("event",  db_event_print_cmd,     0,
  243             "Print all the non-zero evcnt(9) event counters.", "[/f]",NULL) },
  244         { DDB_ADD_CMD("files", db_show_files_cmd,       0,
  245             "Print the files open by process at address",
  246             "[/f] address", NULL) },
  247         { DDB_ADD_CMD("lock",   db_lock_print_cmd,      0,NULL,NULL,NULL) },
  248         { DDB_ADD_CMD("malloc", db_malloc_print_cmd,0,NULL,NULL,NULL) },
  249         { DDB_ADD_CMD("map",    db_map_print_cmd,       0,
  250             "Print the vm_map at address.", "[/f] address",NULL) },
  251         { DDB_ADD_CMD("mount",  db_mount_print_cmd,     0,
  252             "Print the mount structure at address.", "[/f] address",NULL) },
  253         { DDB_ADD_CMD("mqueue", db_show_mqueue_cmd,     0,
  254             "Print the message queues", NULL, NULL) },
  255         { DDB_ADD_CMD("mbuf",   db_mbuf_print_cmd,      0,NULL,NULL,
  256             "-c prints all mbuf chains") },
  257         { DDB_ADD_CMD("ncache", db_namecache_print_cmd, 0,
  258             "Dump the namecache list.", "address",NULL) },
  259         { DDB_ADD_CMD("object", db_object_print_cmd,    0,
  260             "Print the vm_object at address.", "[/f] address",NULL) },
  261         { DDB_ADD_CMD("page",   db_page_print_cmd,      0,
  262             "Print the vm_page at address.", "[/f] address",NULL) },
  263         { DDB_ADD_CMD("pool",   db_pool_print_cmd,      0,
  264             "Print the pool at address.", "[/clp] address",NULL) },
  265         { DDB_ADD_CMD("registers",      db_show_regs,           0,
  266             "Display the register set.", "[/u]",NULL) },
  267         { DDB_ADD_CMD("sched_qs",       db_show_sched_qs,       0,
  268             "Print the state of the scheduler's run queues.",
  269             NULL,NULL) },
  270         { DDB_ADD_CMD("uvmexp", db_uvmexp_print_cmd, 0,
  271             "Print a selection of UVM counters and statistics.",
  272             NULL,NULL) },
  273 #ifdef UVMHIST
  274         { DDB_ADD_CMD("uvmhist", db_uvmhist_print_cmd, 0,
  275             "Print the UVM history logs.",
  276             NULL,NULL) },
  277 #endif
  278         { DDB_ADD_CMD("vnode",  db_vnode_print_cmd,     0,
  279             "Print the vnode at address.", "[/f] address",NULL) },
  280         { DDB_ADD_CMD("watches",        db_listwatch_cmd,       0,
  281             "Display all watchpoints.", NULL,NULL) },
  282         { DDB_ADD_CMD(NULL,             NULL,                   0,NULL,NULL,NULL) }
  283 };
  284 
  285 /* arch/<arch>/<arch>/db_interface.c */
  286 #ifdef DB_MACHINE_COMMANDS
  287 extern const struct db_command db_machine_command_table[];
  288 #endif
  289 
  290 static const struct db_command db_command_table[] = {
  291         { DDB_ADD_CMD("b",              db_breakpoint_cmd,      0,
  292             "Set a breakpoint at address", "[/u] address[,count].",NULL) },
  293         { DDB_ADD_CMD("break",  db_breakpoint_cmd,      0,
  294             "Set a breakpoint at address", "[/u] address[,count].",NULL) },
  295         { DDB_ADD_CMD("bt",             db_stack_trace_cmd,     0,
  296             "Show backtrace.", "See help trace.",NULL) },
  297         { DDB_ADD_CMD("c",              db_continue_cmd,        0,
  298             "Continue execution.", "[/c]",NULL) },
  299         { DDB_ADD_CMD("call",   db_fncall,              CS_OWN,
  300             "Call the function", "address[(expression[,...])]",NULL) },
  301         { DDB_ADD_CMD("callout",        db_show_callout,        0, NULL,
  302             NULL,NULL ) },
  303         { DDB_ADD_CMD("continue",       db_continue_cmd,        0,
  304             "Continue execution.", "[/c]",NULL) },
  305         { DDB_ADD_CMD("d",              db_delete_cmd,          0,
  306             "Delete a breakpoint.", "address | #number",NULL) },
  307         { DDB_ADD_CMD("delete", db_delete_cmd,          0,
  308             "Delete a breakpoint.", "address | #number",NULL) },
  309         { DDB_ADD_CMD("dmesg",  db_dmesg,               0,
  310             "Show kernel message buffer.", "[count]",NULL) },
  311         { DDB_ADD_CMD("dwatch", db_deletewatch_cmd,     0,
  312             "Delete the watchpoint.", "address",NULL) },
  313         { DDB_ADD_CMD("examine",        db_examine_cmd,         CS_SET_DOT,
  314             "Display the address locations.",
  315             "[/modifier] address[,count]",NULL) },
  316         { DDB_ADD_CMD("help",   db_help_print_cmd, CS_OWN|CS_NOREPEAT,
  317             "Display help about commands",
  318             "Use other commands as arguments.",NULL) },
  319         { DDB_ADD_CMD("kill",   db_kill_proc,           CS_OWN,
  320             "Send a signal to the process","pid[,signal_number]",
  321             "   pid:\t\t\tthe process id (may need 0t prefix for decimal)\n"
  322             "   signal_number:\tthe signal to send") },
  323 #ifdef KGDB
  324         { DDB_ADD_CMD("kgdb",   db_kgdb_cmd,    0,      NULL,NULL,NULL) },
  325 #endif
  326         { DDB_ADD_CMD("machine",NULL,CS_MACH,
  327             "Architecture specific functions.",NULL,NULL) },
  328         { DDB_ADD_CMD("match",  db_trace_until_matching_cmd,0,
  329             "Stop at the matching return instruction.","See help next",NULL) },
  330         { DDB_ADD_CMD("next",   db_trace_until_matching_cmd,0,
  331             "Stop at the matching return instruction.","[/p]",NULL) },
  332         { DDB_ADD_CMD("p",              db_print_cmd,           0,
  333             "Print address according to the format.",
  334             "[/axzodurc] address [address ...]",NULL) },
  335         { DDB_ADD_CMD("print",  db_print_cmd,           0,
  336             "Print address according to the format.",
  337             "[/axzodurc] address [address ...]",NULL) },
  338         { DDB_ADD_CMD("ps",             db_show_all_procs,      0,
  339             "Print all processes.","See show all procs",NULL) },
  340         { DDB_ADD_CMD("reboot", db_reboot_cmd,          CS_OWN,
  341             "Reboot","0x1  RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
  342             "0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN",NULL) },
  343         { DDB_ADD_CMD("s",              db_single_step_cmd,     0,
  344             "Single-step count times.","[/p] [,count]",NULL) },
  345         { DDB_ADD_CMD("search", db_search_cmd,          CS_OWN|CS_SET_DOT,
  346             "Search memory from address for value.",
  347             "[/bhl] address value [mask] [,count]",NULL) },
  348         { DDB_ADD_CMD("set",    db_set_cmd,             CS_OWN,
  349             "Set the named variable","$variable [=] expression",NULL) },
  350         { DDB_ADD_CMD("show",   NULL, CS_SHOW,
  351             "Show kernel stats.", NULL,NULL) },
  352         { DDB_ADD_CMD("sifting",        db_sifting_cmd,         CS_OWN,
  353             "Search the symbol tables ","[/F] string",NULL) },
  354         { DDB_ADD_CMD("step",   db_single_step_cmd,     0,
  355             "Single-step count times.","[/p] [,count]",NULL) },
  356         { DDB_ADD_CMD("sync",   db_sync_cmd,            CS_OWN,
  357             "Force a crash dump, and then reboot.",NULL,NULL) },
  358         { DDB_ADD_CMD("trace",  db_stack_trace_cmd,     0,
  359             "Stack trace from frame-address.",
  360             "[/u[l]] [frame-address][,count]",NULL) },
  361         { DDB_ADD_CMD("until",  db_trace_until_call_cmd,0,
  362             "Stop at the next call or return instruction.","[/p]",NULL) },
  363         { DDB_ADD_CMD("w",              db_write_cmd,           CS_MORE|CS_SET_DOT,
  364             "Write the expressions at succeeding locations.",
  365             "[/bhl] address expression [expression ...]",NULL) },
  366         { DDB_ADD_CMD("watch",  db_watchpoint_cmd,      CS_MORE,
  367             "Set a watchpoint for a region. ","address[,size]",NULL) },
  368         { DDB_ADD_CMD("whatis", db_whatis_cmd, 0,
  369             "Describe what an address is", "address", NULL) },
  370         { DDB_ADD_CMD("write",  db_write_cmd,           CS_MORE|CS_SET_DOT,
  371             "Write the expressions at succeeding locations.",
  372             "[/bhl] address expression [expression ...]",NULL) },
  373         { DDB_ADD_CMD("x",              db_examine_cmd,         CS_SET_DOT,
  374             "Display the address locations.",
  375             "[/modifier] address[,count]",NULL) },
  376         { DDB_ADD_CMD(NULL,     NULL,              0, NULL, NULL, NULL) }
  377 };
  378 
  379 static const struct db_command  *db_last_command = NULL;
  380 #if defined(DDB_COMMANDONENTER)
  381 char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
  382 #else /* defined(DDB_COMMANDONENTER) */
  383 char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
  384 #endif /* defined(DDB_COMMANDONENTER) */
  385 #define DB_LINE_SEP     ';'
  386 
  387 /*
  388  * Utility routine - discard tokens through end-of-line.
  389  */
  390 void
  391 db_skip_to_eol(void)
  392 {
  393         int t;
  394 
  395         do {
  396                 t = db_read_token();
  397         } while (t != tEOL);
  398 }
  399 
  400 void
  401 db_error(const char *s)
  402 {
  403 
  404         if (s)
  405                 db_printf("%s", s);
  406         db_flush_lex();
  407         longjmp(db_recover);
  408 }
  409 
  410 /*
  411  * Execute commandlist after ddb start
  412  * This function goes through the command list created from commands and ';'
  413  */
  414 static void
  415 db_execute_commandlist(const char *cmdlist)
  416 {
  417         const char *cmd = cmdlist;
  418         const struct db_command *dummy = NULL;
  419 
  420         while (*cmd != '\0') {
  421                 const char *ep = cmd;
  422 
  423                 while (*ep != '\0' && *ep != DB_LINE_SEP) {
  424                         ep++;
  425                 }
  426                 db_set_line(cmd, ep);
  427                 db_command(&dummy);
  428                 cmd = ep;
  429                 if (*cmd == DB_LINE_SEP) {
  430                         cmd++;
  431                 }
  432         }
  433 }
  434 
  435 /* Initialize ddb command tables */
  436 void
  437 db_init_commands(void)
  438 {
  439         static bool done = false;
  440 
  441         if (done) return;
  442         done = true;
  443 
  444         /* register command tables */
  445         (void)db_register_tbl_entry(DDB_BASE_CMD, &db_base_cmd_builtins);
  446 #ifdef DB_MACHINE_COMMANDS
  447         (void)db_register_tbl_entry(DDB_MACH_CMD, &db_mach_cmd_builtins);
  448 #endif
  449         (void)db_register_tbl_entry(DDB_SHOW_CMD, &db_show_cmd_builtins);
  450 }
  451 
  452 
  453 /*
  454  * Add command table to the specified list
  455  * Arg:
  456  * int type specifies type of command table DDB_SHOW_CMD|DDB_BASE_CMD|DDB_MAC_CMD
  457  * *cmd_tbl poiter to static allocated db_command table
  458  *
  459  * Command table must be NULL terminated array of struct db_command
  460  */
  461 int
  462 db_register_tbl(uint8_t type, const struct db_command *cmd_tbl)
  463 {
  464         struct db_cmd_tbl_en *list_ent;
  465         
  466         /* empty list - ignore */
  467         if (cmd_tbl->name == 0)
  468                 return 0;
  469 
  470         /* force builtin commands to be registered first */
  471         db_init_commands();
  472 
  473         /* now create a list entry for this table */
  474         list_ent = malloc(sizeof(struct db_cmd_tbl_en), M_TEMP, M_ZERO);
  475         if (list_ent == NULL)
  476                 return ENOMEM;
  477         list_ent->db_cmd=cmd_tbl;
  478 
  479         /* and register it */
  480         return db_register_tbl_entry(type, list_ent);
  481 }
  482 
  483 static int
  484 db_register_tbl_entry(uint8_t type, struct db_cmd_tbl_en *list_ent)
  485 {
  486         struct db_cmd_tbl_en_head *list;
  487 
  488         switch(type) {
  489         case DDB_BASE_CMD:
  490                 list = &db_base_cmd_list;
  491                 break;
  492         case DDB_SHOW_CMD:
  493                 list = &db_show_cmd_list;
  494                 break;
  495         case DDB_MACH_CMD:
  496                 list = &db_mach_cmd_list;
  497                 break;
  498         default:
  499                 return ENOENT;
  500         }
  501 
  502         TAILQ_INSERT_TAIL(list, list_ent, db_cmd_next);
  503 
  504         return 0;
  505 }
  506 
  507 /*
  508  * Remove command table specified with db_cmd address == cmd_tbl
  509  */
  510 int
  511 db_unregister_tbl(uint8_t type,const struct db_command *cmd_tbl)
  512 {
  513         struct db_cmd_tbl_en *list_ent;
  514         struct db_cmd_tbl_en_head *list;
  515 
  516         /* find list on which the entry should live */
  517         switch (type) {
  518         case DDB_BASE_CMD:
  519                 list=&db_base_cmd_list;
  520                 break;
  521         case DDB_SHOW_CMD:
  522                 list=&db_show_cmd_list;
  523                 break;
  524         case DDB_MACH_CMD:
  525                 list=&db_mach_cmd_list;
  526                 break;
  527         default:
  528                 return EINVAL;
  529         }
  530 
  531         TAILQ_FOREACH (list_ent, list, db_cmd_next) {
  532                 if (list_ent->db_cmd == cmd_tbl){
  533                         TAILQ_REMOVE(list,
  534                             list_ent, db_cmd_next);
  535                         free(list_ent,M_TEMP);
  536                         return 0;
  537                 }
  538         }
  539         return ENOENT;
  540 }
  541 
  542 /* This function is called from machine trap code. */
  543 void
  544 db_command_loop(void)
  545 {
  546         label_t db_jmpbuf;
  547         label_t *savejmp;
  548 
  549         /*
  550          * Initialize 'prev' and 'next' to dot.
  551          */
  552         db_prev = db_dot;
  553         db_next = db_dot;
  554 
  555         db_cmd_loop_done = false;
  556 
  557         /* Init default command tables add machine, base,
  558            show command tables to the list */
  559         db_init_commands();
  560 
  561         /* save context for return from ddb */
  562         savejmp = db_recover;
  563         db_recover = &db_jmpbuf;
  564         (void) setjmp(&db_jmpbuf);
  565 
  566         /* Execute default ddb start commands */
  567         db_execute_commandlist(db_cmd_on_enter);
  568 
  569         (void) setjmp(&db_jmpbuf);
  570         while (!db_cmd_loop_done) {
  571                 if (db_print_position() != 0)
  572                         db_printf("\n");
  573                 db_output_line = 0;
  574 
  575 
  576 #ifdef MULTIPROCESSOR
  577                 db_printf("db{%ld}> ", (long)cpu_number());
  578 #else
  579                 db_printf("db> ");
  580 #endif
  581                 (void) db_read_line();
  582 
  583                 db_command(&db_last_command);
  584         }
  585 
  586         db_recover = savejmp;
  587 }
  588 
  589 /*
  590  * Search command table for command prefix
  591  */
  592 static int
  593 db_cmd_search_table(const char *name,
  594                     const struct db_command *table,
  595                     const struct db_command **cmdp)
  596 {
  597 
  598         const struct db_command *cmd;
  599         int result;
  600 
  601         result = CMD_NONE;
  602         *cmdp = NULL;
  603 
  604         for (cmd = table; cmd->name != 0; cmd++) {
  605                 const char *lp;
  606                 const char *rp;
  607 
  608                 lp = name;
  609                 rp = cmd->name;
  610                 while (*lp != '\0' && *lp == *rp) {
  611                         rp++;
  612                         lp++;
  613                 }
  614 
  615                 if (*lp != '\0') /* mismatch or extra chars in name */
  616                         continue;
  617 
  618                 if (*rp == '\0') { /* exact match */
  619                         *cmdp = cmd;
  620                         return (CMD_EXACT);
  621                 }
  622 
  623                 /* prefix match: end of name, not end of command */
  624                 if (result == CMD_NONE) {
  625                         result = CMD_PREFIX;
  626                         *cmdp = cmd;
  627                 }
  628                 else if (result == CMD_PREFIX) {
  629                         result = CMD_AMBIGUOUS;
  630                         *cmdp = NULL;
  631                 }
  632         }
  633 
  634         return (result);
  635 }
  636 
  637 
  638 /*
  639  * Search list of command tables for command
  640  */
  641 static int
  642 db_cmd_search(const char *name,
  643               struct db_cmd_tbl_en_head *list_head,
  644               const struct db_command **cmdp)
  645 {
  646         struct db_cmd_tbl_en *list_ent;
  647         const struct db_command *found_command;
  648         bool accept_prefix_match;
  649         int result;
  650 
  651         result = CMD_NONE;
  652         found_command = NULL;
  653         accept_prefix_match = true;
  654 
  655         TAILQ_FOREACH(list_ent, list_head, db_cmd_next) {
  656                 const struct db_command *cmd;
  657                 int found;
  658 
  659                 found = db_cmd_search_table(name, list_ent->db_cmd, &cmd);
  660                 if (found == CMD_EXACT) {
  661                         result = CMD_EXACT;
  662                         found_command = cmd;
  663                         break;
  664                 }
  665 
  666                 if (found == CMD_PREFIX) {
  667                         if (accept_prefix_match) {
  668                                 /*
  669                                  * Continue search, but note current result
  670                                  * in case we won't find anything else.
  671                                  */
  672                                 accept_prefix_match = false;
  673                                 result = CMD_PREFIX;
  674                                 found_command = cmd;
  675                         } else {
  676                                 /*
  677                                  * Watch out for globally ambiguous
  678                                  * prefix match that is not locally
  679                                  * ambiguous - with one match in one
  680                                  * table and another match(es) in
  681                                  * another table.
  682                                  */
  683                                 result = CMD_AMBIGUOUS;
  684                                 found_command = NULL;
  685                         }
  686                 }
  687                 else if (found == CMD_AMBIGUOUS) {
  688                         accept_prefix_match = false;
  689                         result = CMD_AMBIGUOUS;
  690                         found_command = NULL;
  691                 }
  692         }
  693 
  694         *cmdp = found_command;
  695         return result;
  696 }
  697 
  698 static void
  699 db_cmd_search_failed(char *name, int search_result)
  700 {
  701         if (search_result == CMD_NONE)
  702                 db_printf("No such command: %s\n", name);
  703         else
  704                 db_printf("Ambiguous command: %s\n", name);
  705 }
  706 
  707 
  708 /*
  709  * List commands to the console.
  710  */
  711 static void
  712 db_cmd_list(const struct db_cmd_tbl_en_head *list)
  713 {
  714 
  715         struct db_cmd_tbl_en *list_ent;
  716         const struct db_command *table;
  717         size_t          i, j, w, columns, lines, numcmds, width=0;
  718         const char      *p;
  719 
  720         TAILQ_FOREACH(list_ent,list,db_cmd_next) {
  721                 table = list_ent->db_cmd;
  722                 for (i = 0; table[i].name != NULL; i++) {
  723                         w = strlen(table[i].name);
  724                         if (w > width)
  725                                 width = w;
  726                 }
  727         }
  728 
  729         width = DB_NEXT_TAB(width);
  730 
  731         columns = db_max_width / width;
  732         if (columns == 0)
  733                 columns = 1;
  734 
  735         TAILQ_FOREACH(list_ent,list,db_cmd_next) {
  736                 table = list_ent->db_cmd;
  737 
  738                 for (numcmds = 0; table[numcmds].name != NULL; numcmds++)
  739                         ;
  740                 lines = (numcmds + columns - 1) / columns;
  741 
  742                 for (i = 0; i < lines; i++) {
  743                         for (j = 0; j < columns; j++) {
  744                                 p = table[j * lines + i].name;
  745                                 if (p)
  746                                         db_printf("%s", p);
  747                                 if (j * lines + i + lines >= numcmds) {
  748                                         db_putchar('\n');
  749                                         break;
  750                                 }
  751                                 if (p) {
  752                                         w = strlen(p);
  753                                         while (w < width) {
  754                                                 w = DB_NEXT_TAB(w);
  755                                                 db_putchar('\t');
  756                                         }
  757                                 }
  758                         }
  759                 }
  760         }
  761         return;
  762 }
  763 
  764 /*
  765  * Read complete command with all subcommands, starting with current
  766  * db_tok_string. If subcommand is missing, print the list of all
  767  * subcommands.  If command/subcommand is not found, print an error
  768  * message.  Returns pointer to "leaf" command or NULL.
  769  */
  770 static const struct db_command *
  771 db_read_command(void)
  772 {
  773         const struct db_command *command;
  774         struct db_cmd_tbl_en_head *list;
  775         int found;
  776         int t;
  777 
  778         list = &db_base_cmd_list;
  779         do {
  780                 found = db_cmd_search(db_tok_string, list, &command);
  781                 if (command == NULL) {
  782                         db_cmd_search_failed(db_tok_string, found);
  783                         db_flush_lex();
  784                         return NULL;
  785                 }
  786 
  787                 if (command->flag == CS_SHOW)
  788                         list = &db_show_cmd_list;
  789                 else if (command->flag == CS_MACH)
  790                         list = &db_mach_cmd_list;
  791                 else if (command->flag == CS_COMPAT)
  792                         /* same list */;
  793                 else
  794                         break; /* expect no more subcommands */
  795 
  796                 t = db_read_token(); /* read subcommand */
  797                 if (t != tIDENT) {
  798                         /* if none given - just print all of them */
  799                         db_cmd_list(list);
  800                         db_flush_lex();
  801                         return NULL;
  802                 }
  803         } while (list != NULL);
  804 
  805         return command;
  806 }
  807 
  808 /*
  809  * Parse command line and execute apropriate function.
  810  */
  811 static void
  812 db_command(const struct db_command **last_cmdp)
  813 {
  814         const struct db_command *command;
  815         static db_expr_t last_count;
  816         db_expr_t       addr, count;
  817         char            modif[TOK_STRING_SIZE];
  818         
  819         int                     t;
  820         bool            have_addr = false;
  821 
  822         command = NULL;
  823         last_count = 0;
  824         
  825         t = db_read_token();
  826         if ((t == tEOL) || (t == tCOMMA)) {
  827                 /*
  828                  * An empty line repeats last command, at 'next'.
  829                  * Only a count repeats the last command with the new count.
  830                  */
  831                 command = *last_cmdp;
  832 
  833                 if (!command)
  834                         return;
  835 
  836                 addr = (db_expr_t)db_next;
  837                 if (t == tCOMMA) {
  838                         if (!db_expression(&count)) {
  839                                 db_printf("Count missing\n");
  840                                 db_flush_lex();
  841                                 return;
  842                         }
  843                 } else
  844                         count = last_count;
  845                 have_addr = false;
  846                 modif[0] = '\0';
  847                 db_skip_to_eol();
  848 
  849         } else if (t == tEXCL) {
  850                 db_fncall(0, 0, 0, NULL);
  851                 return;
  852 
  853         } else if (t != tIDENT) {
  854                 db_printf("?\n");
  855                 db_flush_lex();
  856                 return;
  857 
  858         } else {
  859 
  860                 command = db_read_command();
  861                 if (command == NULL)
  862                         return;
  863 
  864                 if ((command->flag & CS_OWN) == 0) {
  865 
  866                         /*
  867                          * Standard syntax:
  868                          * command [/modifier] [addr] [,count]
  869                          */
  870                         t = db_read_token(); /* get modifier */
  871                         if (t == tSLASH) {
  872                                 t = db_read_token();
  873                                 if (t != tIDENT) {
  874                                         db_printf("Bad modifier\n");
  875                                         db_flush_lex();
  876                                         return;
  877                                 }
  878                                 /* save modifier */
  879                                 strlcpy(modif, db_tok_string, sizeof(modif));
  880 
  881                         } else {
  882                                 db_unread_token(t);
  883                                 modif[0] = '\0';
  884                         }
  885 
  886                         if (db_expression(&addr)) { /*get address*/
  887                                 db_dot = (db_addr_t) addr;
  888                                 db_last_addr = db_dot;
  889                                 have_addr = true;
  890                         } else {
  891                                 addr = (db_expr_t) db_dot;
  892                                 have_addr = false;
  893                         }
  894 
  895                         t = db_read_token();
  896                         if (t == tCOMMA) { /*Get count*/
  897                                 if (!db_expression(&count)) {
  898                                         db_printf("Count missing\n");
  899                                         db_flush_lex();
  900                                         return;
  901                                 }
  902                         } else {
  903                                 db_unread_token(t);
  904                                 count = -1;
  905                         }
  906                         if ((command->flag & CS_MORE) == 0) {
  907                                 db_skip_to_eol();
  908                         }
  909                 }
  910         }
  911 
  912         if (command != NULL && command->flag & CS_NOREPEAT) {
  913                 *last_cmdp = NULL;
  914                 last_count = 0;
  915         } else {
  916                 *last_cmdp = command;
  917                 last_count = count;
  918         }
  919 
  920 
  921         if (command != NULL) {
  922                 /*
  923                  * Execute the command.
  924                  */
  925                 if (command->fcn != NULL)
  926                         (*command->fcn)(addr, have_addr, count, modif);
  927 
  928                 if (command->flag & CS_SET_DOT) {
  929                         /*
  930                          * If command changes dot, set dot to
  931                          * previous address displayed (if 'ed' style).
  932                          */
  933                         if (db_ed_style)
  934                                 db_dot = db_prev;
  935                         else
  936                                 db_dot = db_next;
  937                 } else {
  938                         /*
  939                          * If command does not change dot,
  940                          * set 'next' location to be the same.
  941                          */
  942                         db_next = db_dot;
  943                 }
  944         }
  945 }
  946 
  947 /*
  948  * Print help for commands
  949  */
  950 static void
  951 db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  952 const char *modif)
  953 {
  954         const struct db_command *command;
  955         int t;
  956 
  957         t = db_read_token();
  958 
  959         /* is there another command after the "help"? */
  960         if (t != tIDENT) {
  961                 /* print base commands */
  962                 db_cmd_list(&db_base_cmd_list);
  963                 return;
  964         }
  965 
  966         command = db_read_command();
  967         if (command == NULL)
  968                 return;
  969 
  970 #ifdef DDB_VERBOSE_HELP
  971         db_printf("Command: %s\n", command->name);
  972         if (command->cmd_descr != NULL)
  973                 db_printf(" Description: %s\n", command->cmd_descr);
  974         if (command->cmd_arg != NULL)
  975                 db_printf(" Arguments: %s\n", command->cmd_arg);
  976         if (command->cmd_arg_help != NULL)
  977                 db_printf(" Arguments description:\n%s\n",
  978                           command->cmd_arg_help);
  979         if ((command->cmd_arg == NULL) && (command->cmd_descr == NULL))
  980                 db_printf(" No help message.\n");
  981 #endif
  982 
  983         db_skip_to_eol();
  984 }
  985 
  986 /*ARGSUSED*/
  987 static void
  988 db_map_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
  989     const char *modif)
  990 {
  991         bool full = false;
  992 
  993         if (modif[0] == 'f')
  994                 full = true;
  995 
  996         if (have_addr == false)
  997                 addr = (db_expr_t)(uintptr_t) kernel_map;
  998 
  999         uvm_map_printit((struct vm_map *)(uintptr_t) addr, full, db_printf);
 1000 }
 1001 
 1002 /*ARGSUSED*/
 1003 static void
 1004 db_malloc_print_cmd(db_expr_t addr, bool have_addr,
 1005     db_expr_t count, const char *modif)
 1006 {
 1007 
 1008 #ifdef MALLOC_DEBUG
 1009         if (!have_addr)
 1010                 addr = 0;
 1011 
 1012         debug_malloc_printit(db_printf, (vaddr_t) addr);
 1013 #else
 1014         db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
 1015 #endif /* MALLOC_DEBUG */
 1016 }
 1017 
 1018 /*ARGSUSED*/
 1019 static void
 1020 db_object_print_cmd(db_expr_t addr, bool have_addr,
 1021     db_expr_t count, const char *modif)
 1022 {
 1023         bool full = false;
 1024 
 1025         if (modif[0] == 'f')
 1026                 full = true;
 1027 
 1028         uvm_object_printit((struct uvm_object *)(uintptr_t) addr, full,
 1029             db_printf);
 1030 }
 1031 
 1032 /*ARGSUSED*/
 1033 static void
 1034 db_page_print_cmd(db_expr_t addr, bool have_addr,
 1035     db_expr_t count, const char *modif)
 1036 {
 1037         bool full = false;
 1038 
 1039         if (modif[0] == 'f')
 1040                 full = true;
 1041 
 1042         uvm_page_printit((struct vm_page *)(uintptr_t) addr, full, db_printf);
 1043 }
 1044 
 1045 /*ARGSUSED*/
 1046 static void
 1047 db_show_all_pages(db_expr_t addr, bool have_addr,
 1048     db_expr_t count, const char *modif)
 1049 {
 1050 
 1051         uvm_page_printall(db_printf);
 1052 }
 1053 
 1054 /*ARGSUSED*/
 1055 static void
 1056 db_buf_print_cmd(db_expr_t addr, bool have_addr,
 1057     db_expr_t count, const char *modif)
 1058 {
 1059         bool full = false;
 1060 
 1061         if (modif[0] == 'f')
 1062                 full = true;
 1063 
 1064         vfs_buf_print((struct buf *)(uintptr_t) addr, full, db_printf);
 1065 }
 1066 
 1067 /*ARGSUSED*/
 1068 static void
 1069 db_event_print_cmd(db_expr_t addr, bool have_addr,
 1070     db_expr_t count, const char *modif)
 1071 {
 1072         bool full = false;
 1073 
 1074         if (modif[0] == 'f')
 1075                 full = true;
 1076 
 1077         event_print(full, db_printf);
 1078 }
 1079 
 1080 /*ARGSUSED*/
 1081 static void
 1082 db_vnode_print_cmd(db_expr_t addr, bool have_addr,
 1083     db_expr_t count, const char *modif)
 1084 {
 1085         bool full = false;
 1086 
 1087         if (modif[0] == 'f')
 1088                 full = true;
 1089 
 1090         vfs_vnode_print((struct vnode *)(uintptr_t) addr, full, db_printf);
 1091 }
 1092 
 1093 static void
 1094 db_mount_print_cmd(db_expr_t addr, bool have_addr,
 1095     db_expr_t count, const char *modif)
 1096 {
 1097         bool full = false;
 1098 
 1099         if (modif[0] == 'f')
 1100                 full = true;
 1101 
 1102         vfs_mount_print((struct mount *)(uintptr_t) addr, full, db_printf);
 1103 }
 1104 
 1105 /*ARGSUSED*/
 1106 static void
 1107 db_mbuf_print_cmd(db_expr_t addr, bool have_addr,
 1108     db_expr_t count, const char *modif)
 1109 {
 1110 
 1111         m_print((const struct mbuf *)(uintptr_t) addr, modif, db_printf);
 1112 }
 1113 
 1114 /*ARGSUSED*/
 1115 static void
 1116 db_pool_print_cmd(db_expr_t addr, bool have_addr,
 1117     db_expr_t count, const char *modif)
 1118 {
 1119 
 1120         pool_printit((struct pool *)(uintptr_t) addr, modif, db_printf);
 1121 }
 1122 
 1123 /*ARGSUSED*/
 1124 static void
 1125 db_namecache_print_cmd(db_expr_t addr, bool have_addr,
 1126     db_expr_t count, const char *modif)
 1127 {
 1128 
 1129         namecache_print((struct vnode *)(uintptr_t) addr, db_printf);
 1130 }
 1131 
 1132 /*ARGSUSED*/
 1133 static void
 1134 db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
 1135     db_expr_t count, const char *modif)
 1136 {
 1137 
 1138         uvmexp_print(db_printf);
 1139 }
 1140 
 1141 #ifdef UVMHIST
 1142 /*ARGSUSED*/
 1143 static void
 1144 db_uvmhist_print_cmd(db_expr_t addr, bool have_addr,
 1145     db_expr_t count, const char *modif)
 1146 {
 1147 
 1148         uvmhist_print(db_printf);
 1149 }
 1150 #endif
 1151 
 1152 /*ARGSUSED*/
 1153 static void
 1154 db_lock_print_cmd(db_expr_t addr, bool have_addr,
 1155     db_expr_t count, const char *modif)
 1156 {
 1157 
 1158         lockdebug_lock_print((void *)(uintptr_t)addr, db_printf);
 1159 }
 1160 
 1161 /*
 1162  * Call random function:
 1163  * !expr(arg,arg,arg)
 1164  */
 1165 /*ARGSUSED*/
 1166 static void
 1167 db_fncall(db_expr_t addr, bool have_addr,
 1168     db_expr_t count, const char *modif)
 1169 {
 1170         db_expr_t       fn_addr;
 1171 #define MAXARGS         11
 1172         db_expr_t       args[MAXARGS];
 1173         int             nargs = 0;
 1174         db_expr_t       retval;
 1175         db_expr_t       (*func)(db_expr_t, ...);
 1176         int             t;
 1177 
 1178         if (!db_expression(&fn_addr)) {
 1179                 db_printf("Bad function\n");
 1180                 db_flush_lex();
 1181                 return;
 1182         }
 1183         func = (db_expr_t (*)(db_expr_t, ...))(uintptr_t) fn_addr;
 1184 
 1185         t = db_read_token();
 1186         if (t == tLPAREN) {
 1187                 if (db_expression(&args[0])) {
 1188                         nargs++;
 1189                         while ((t = db_read_token()) == tCOMMA) {
 1190                                 if (nargs == MAXARGS) {
 1191                                         db_printf("Too many arguments\n");
 1192                                         db_flush_lex();
 1193                                         return;
 1194                                 }
 1195                                 if (!db_expression(&args[nargs])) {
 1196                                         db_printf("Argument missing\n");
 1197                                         db_flush_lex();
 1198                                         return;
 1199                                 }
 1200                                 nargs++;
 1201                         }
 1202                         db_unread_token(t);
 1203                 }
 1204                 if (db_read_token() != tRPAREN) {
 1205                         db_printf("?\n");
 1206                         db_flush_lex();
 1207                         return;
 1208                 }
 1209         }
 1210         db_skip_to_eol();
 1211 
 1212         while (nargs < MAXARGS) {
 1213                 args[nargs++] = 0;
 1214         }
 1215 
 1216         retval = (*func)(args[0], args[1], args[2], args[3], args[4],
 1217                          args[5], args[6], args[7], args[8], args[9]);
 1218         db_printf("%s\n", db_num_to_str(retval));
 1219 }
 1220 
 1221 static void
 1222 db_reboot_cmd(db_expr_t addr, bool have_addr,
 1223     db_expr_t count, const char *modif)
 1224 {
 1225         db_expr_t bootflags;
 1226 
 1227         /* Flags, default to RB_AUTOBOOT */
 1228         if (!db_expression(&bootflags))
 1229                 bootflags = (db_expr_t)RB_AUTOBOOT;
 1230         if (db_read_token() != tEOL) {
 1231                 db_error("?\n");
 1232                 /*NOTREACHED*/
 1233         }
 1234         /*
 1235          * We are leaving DDB, never to return upward.
 1236          * Clear db_recover so that we can debug faults in functions
 1237          * called from cpu_reboot.
 1238          */
 1239         db_recover = 0;
 1240         cpu_reboot((int)bootflags, NULL);
 1241 }
 1242 
 1243 static void
 1244 db_sifting_cmd(db_expr_t addr, bool have_addr,
 1245     db_expr_t count, const char *modif)
 1246 {
 1247         int     mode, t;
 1248 
 1249         t = db_read_token();
 1250         if (t == tSLASH) {
 1251                 t = db_read_token();
 1252                 if (t != tIDENT) {
 1253                         bad_modifier:
 1254                         db_printf("Bad modifier\n");
 1255                         db_flush_lex();
 1256                         return;
 1257                 }
 1258                 if (!strcmp(db_tok_string, "F"))
 1259                         mode = 'F';
 1260                 else
 1261                         goto bad_modifier;
 1262                 t = db_read_token();
 1263         } else
 1264                 mode = 0;
 1265 
 1266         if (t == tIDENT)
 1267                 db_sifting(db_tok_string, mode);
 1268         else {
 1269                 db_printf("Bad argument (non-string)\n");
 1270                 db_flush_lex();
 1271         }
 1272 }
 1273 
 1274 static void
 1275 db_stack_trace_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
 1276 {
 1277         register const char *cp = modif;
 1278         register char c;
 1279         void (*pr)(const char *, ...);
 1280 
 1281         pr = db_printf;
 1282         while ((c = *cp++) != 0)
 1283                 if (c == 'l')
 1284                         pr = printf;
 1285 
 1286         if (count == -1)
 1287                 count = 65535;
 1288 
 1289         db_stack_trace_print(addr, have_addr, count, modif, pr);
 1290 }
 1291 
 1292 static void
 1293 db_sync_cmd(db_expr_t addr, bool have_addr,
 1294     db_expr_t count, const char *modif)
 1295 {
 1296 
 1297         /*
 1298          * We are leaving DDB, never to return upward.
 1299          * Clear db_recover so that we can debug faults in functions
 1300          * called from cpu_reboot.
 1301          */
 1302         db_recover = 0;
 1303         panicstr = "dump forced via kernel debugger";
 1304         cpu_reboot(RB_DUMP, NULL);
 1305 }
 1306 
 1307 /*
 1308  * Describe what an address is
 1309  */
 1310 void
 1311 db_whatis_cmd(db_expr_t address, bool have_addr,
 1312     db_expr_t count, const char *modif)
 1313 {
 1314         const uintptr_t addr = (uintptr_t)address;
 1315 
 1316         lwp_whatis(addr, db_printf);
 1317         pool_whatis(addr, db_printf);
 1318         vmem_whatis(addr, db_printf);
 1319         uvm_whatis(addr, db_printf);
 1320 }

Cache object: c76cebeef0a59940258e65efd5ed5195


[ 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.