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