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