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