Home | History | Annotate | Line # | Download | only in ddb
db_command.c revision 1.114.6.4
      1  1.114.6.4  mjf /*	$NetBSD: db_command.c,v 1.114.6.4 2008/10/05 20:11:28 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.4  mjf __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.114.6.4 2008/10/05 20:11:28 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.4  mjf 	{ DDB_ADD_CMD("mqueue", db_show_mqueue_cmd,	0,
    250  1.114.6.4  mjf 	    "Print the message queues", NULL, NULL) },
    251  1.114.6.2  mjf 	{ DDB_ADD_CMD("mbuf",	db_mbuf_print_cmd,	0,NULL,NULL,
    252  1.114.6.2  mjf 	    "-c prints all mbuf chains") },
    253  1.114.6.2  mjf 	{ DDB_ADD_CMD("ncache",	db_namecache_print_cmd,	0,
    254  1.114.6.2  mjf 	    "Dump the namecache list.", "address",NULL) },
    255  1.114.6.2  mjf 	{ DDB_ADD_CMD("object",	db_object_print_cmd,	0,
    256  1.114.6.2  mjf 	    "Print the vm_object at address.", "[/f] address",NULL) },
    257  1.114.6.2  mjf 	{ DDB_ADD_CMD("page",	db_page_print_cmd,	0,
    258  1.114.6.2  mjf 	    "Print the vm_page at address.", "[/f] address",NULL) },
    259  1.114.6.2  mjf 	{ DDB_ADD_CMD("pool",	db_pool_print_cmd,	0,
    260  1.114.6.2  mjf 	    "Print the pool at address.", "[/clp] address",NULL) },
    261  1.114.6.2  mjf 	{ DDB_ADD_CMD("registers",	db_show_regs,		0,
    262  1.114.6.2  mjf 	    "Display the register set.", "[/u]",NULL) },
    263  1.114.6.2  mjf 	{ DDB_ADD_CMD("sched_qs",	db_show_sched_qs,	0,
    264  1.114.6.2  mjf 	    "Print the state of the scheduler's run queues.",
    265  1.114.6.2  mjf 	    NULL,NULL) },
    266  1.114.6.2  mjf 	{ DDB_ADD_CMD("uvmexp",	db_uvmexp_print_cmd, 0,
    267  1.114.6.2  mjf 	    "Print a selection of UVM counters and statistics.",
    268  1.114.6.2  mjf 	    NULL,NULL) },
    269  1.114.6.3  mjf #ifdef UVMHIST
    270  1.114.6.3  mjf 	{ DDB_ADD_CMD("uvmhist", db_uvmhist_print_cmd, 0,
    271  1.114.6.3  mjf 	    "Print the UVM history logs.",
    272  1.114.6.3  mjf 	    NULL,NULL) },
    273  1.114.6.3  mjf #endif
    274  1.114.6.2  mjf 	{ DDB_ADD_CMD("vnode",	db_vnode_print_cmd,	0,
    275  1.114.6.2  mjf 	    "Print the vnode at address.", "[/f] address",NULL) },
    276  1.114.6.2  mjf 	{ DDB_ADD_CMD("watches",	db_listwatch_cmd, 	0,
    277  1.114.6.2  mjf 	    "Display all watchpoints.", NULL,NULL) },
    278  1.114.6.2  mjf 	{ DDB_ADD_CMD(NULL,		NULL,			0,NULL,NULL,NULL) }
    279  1.114.6.2  mjf };
    280  1.114.6.2  mjf 
    281  1.114.6.2  mjf /* arch/<arch>/<arch>/db_interface.c */
    282  1.114.6.2  mjf #ifdef DB_MACHINE_COMMANDS
    283  1.114.6.2  mjf extern const struct db_command db_machine_command_table[];
    284  1.114.6.2  mjf #endif
    285  1.114.6.2  mjf 
    286  1.114.6.2  mjf static const struct db_command db_command_table[] = {
    287  1.114.6.2  mjf 	{ DDB_ADD_CMD("b",		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("break",	db_breakpoint_cmd,	0,
    290  1.114.6.2  mjf 	    "Set a breakpoint at address", "[/u] address[,count].",NULL) },
    291  1.114.6.2  mjf 	{ DDB_ADD_CMD("bt",		db_stack_trace_cmd,	0,
    292  1.114.6.2  mjf 	    "Show backtrace.", "See help trace.",NULL) },
    293  1.114.6.2  mjf 	{ DDB_ADD_CMD("c",		db_continue_cmd,	0,
    294  1.114.6.2  mjf 	    "Continue execution.", "[/c]",NULL) },
    295  1.114.6.2  mjf 	{ DDB_ADD_CMD("call",	db_fncall,		CS_OWN,
    296  1.114.6.2  mjf 	    "Call the function", "address[(expression[,...])]",NULL) },
    297  1.114.6.2  mjf 	{ DDB_ADD_CMD("callout",	db_show_callout,	0, NULL,
    298  1.114.6.2  mjf 	    NULL,NULL ) },
    299  1.114.6.2  mjf 	{ DDB_ADD_CMD("continue",	db_continue_cmd,	0,
    300  1.114.6.2  mjf 	    "Continue execution.", "[/c]",NULL) },
    301  1.114.6.2  mjf 	{ DDB_ADD_CMD("d",		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("delete",	db_delete_cmd,		0,
    304  1.114.6.2  mjf 	    "Delete a breakpoint.", "address | #number",NULL) },
    305  1.114.6.2  mjf 	{ DDB_ADD_CMD("dmesg",	db_dmesg,		0,
    306  1.114.6.2  mjf 	    "Show kernel message buffer.", "[count]",NULL) },
    307  1.114.6.2  mjf 	{ DDB_ADD_CMD("dwatch",	db_deletewatch_cmd,	0,
    308  1.114.6.2  mjf 	    "Delete the watchpoint.", "address",NULL) },
    309  1.114.6.2  mjf 	{ DDB_ADD_CMD("examine",	db_examine_cmd,		CS_SET_DOT,
    310  1.114.6.2  mjf 	    "Display the address locations.",
    311  1.114.6.2  mjf 	    "[/modifier] address[,count]",NULL) },
    312  1.114.6.2  mjf 	{ DDB_ADD_CMD("help",   db_help_print_cmd, CS_OWN|CS_NOREPEAT,
    313  1.114.6.2  mjf 	    "Display help about commands",
    314  1.114.6.2  mjf 	    "Use other commands as arguments.",NULL) },
    315  1.114.6.2  mjf 	{ DDB_ADD_CMD("kill",	db_kill_proc,		CS_OWN,
    316  1.114.6.2  mjf 	    "Send a signal to the process","pid[,signal_number]",
    317  1.114.6.2  mjf 	    "   pid:\t\t\tthe process id (may need 0t prefix for decimal)\n"
    318  1.114.6.2  mjf 	    "   signal_number:\tthe signal to send") },
    319  1.114.6.2  mjf #ifdef KGDB
    320  1.114.6.2  mjf 	{ DDB_ADD_CMD("kgdb",	db_kgdb_cmd,	0,	NULL,NULL,NULL) },
    321  1.114.6.2  mjf #endif
    322  1.114.6.2  mjf 	{ DDB_ADD_CMD("machine",NULL,CS_MACH,
    323  1.114.6.2  mjf 	    "Architecture specific functions.",NULL,NULL) },
    324  1.114.6.2  mjf 	{ DDB_ADD_CMD("match",	db_trace_until_matching_cmd,0,
    325  1.114.6.2  mjf 	    "Stop at the matching return instruction.","See help next",NULL) },
    326  1.114.6.2  mjf 	{ DDB_ADD_CMD("next",	db_trace_until_matching_cmd,0,
    327  1.114.6.2  mjf 	    "Stop at the matching return instruction.","[/p]",NULL) },
    328  1.114.6.2  mjf 	{ DDB_ADD_CMD("p",		db_print_cmd,		0,
    329  1.114.6.2  mjf 	    "Print address according to the format.",
    330  1.114.6.2  mjf 	    "[/axzodurc] address [address ...]",NULL) },
    331  1.114.6.2  mjf 	{ DDB_ADD_CMD("print",	db_print_cmd,		0,
    332  1.114.6.2  mjf 	    "Print address according to the format.",
    333  1.114.6.2  mjf 	    "[/axzodurc] address [address ...]",NULL) },
    334  1.114.6.2  mjf 	{ DDB_ADD_CMD("ps",		db_show_all_procs,	0,
    335  1.114.6.2  mjf 	    "Print all processes.","See show all procs",NULL) },
    336  1.114.6.2  mjf 	{ DDB_ADD_CMD("reboot",	db_reboot_cmd,		CS_OWN,
    337  1.114.6.2  mjf 	    "Reboot","0x1  RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
    338  1.114.6.2  mjf 	    "0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN",NULL) },
    339  1.114.6.2  mjf 	{ DDB_ADD_CMD("s",		db_single_step_cmd,	0,
    340  1.114.6.2  mjf 	    "Single-step count times.","[/p] [,count]",NULL) },
    341  1.114.6.2  mjf 	{ DDB_ADD_CMD("search",	db_search_cmd,		CS_OWN|CS_SET_DOT,
    342  1.114.6.2  mjf 	    "Search memory from address for value.",
    343  1.114.6.2  mjf 	    "[/bhl] address value [mask] [,count]",NULL) },
    344  1.114.6.2  mjf 	{ DDB_ADD_CMD("set",	db_set_cmd,		CS_OWN,
    345  1.114.6.2  mjf 	    "Set the named variable","$variable [=] expression",NULL) },
    346  1.114.6.2  mjf 	{ DDB_ADD_CMD("show",	NULL, CS_SHOW,
    347  1.114.6.2  mjf 	    "Show kernel stats.", NULL,NULL) },
    348  1.114.6.2  mjf 	{ DDB_ADD_CMD("sifting",	db_sifting_cmd,		CS_OWN,
    349  1.114.6.2  mjf 	    "Search the symbol tables ","[/F] string",NULL) },
    350  1.114.6.2  mjf 	{ DDB_ADD_CMD("step",	db_single_step_cmd,	0,
    351  1.114.6.2  mjf 	    "Single-step count times.","[/p] [,count]",NULL) },
    352  1.114.6.2  mjf 	{ DDB_ADD_CMD("sync",	db_sync_cmd,		CS_OWN,
    353  1.114.6.2  mjf 	    "Force a crash dump, and then reboot.",NULL,NULL) },
    354  1.114.6.2  mjf 	{ DDB_ADD_CMD("trace",	db_stack_trace_cmd,	0,
    355  1.114.6.2  mjf 	    "Stack trace from frame-address.",
    356  1.114.6.2  mjf 	    "[/u[l]] [frame-address][,count]",NULL) },
    357  1.114.6.2  mjf 	{ DDB_ADD_CMD("until",	db_trace_until_call_cmd,0,
    358  1.114.6.2  mjf 	    "Stop at the next call or return instruction.","[/p]",NULL) },
    359  1.114.6.2  mjf 	{ DDB_ADD_CMD("w",		db_write_cmd,		CS_MORE|CS_SET_DOT,
    360  1.114.6.2  mjf 	    "Write the expressions at succeeding locations.",
    361  1.114.6.2  mjf 	    "[/bhl] address expression [expression ...]",NULL) },
    362  1.114.6.2  mjf 	{ DDB_ADD_CMD("watch",	db_watchpoint_cmd,	CS_MORE,
    363  1.114.6.2  mjf 	    "Set a watchpoint for a region. ","address[,size]",NULL) },
    364  1.114.6.2  mjf 	{ DDB_ADD_CMD("whatis",	db_whatis_cmd, 0,
    365  1.114.6.2  mjf 	    "Describe what an address is", "address", NULL) },
    366  1.114.6.2  mjf 	{ DDB_ADD_CMD("write",	db_write_cmd,		CS_MORE|CS_SET_DOT,
    367  1.114.6.2  mjf 	    "Write the expressions at succeeding locations.",
    368  1.114.6.2  mjf 	    "[/bhl] address expression [expression ...]",NULL) },
    369  1.114.6.2  mjf 	{ DDB_ADD_CMD("x",		db_examine_cmd,		CS_SET_DOT,
    370  1.114.6.2  mjf 	    "Display the address locations.",
    371  1.114.6.2  mjf 	    "[/modifier] address[,count]",NULL) },
    372  1.114.6.2  mjf 	{ DDB_ADD_CMD(NULL, 	NULL,		   0, NULL, NULL, NULL) }
    373  1.114.6.2  mjf };
    374  1.114.6.2  mjf 
    375  1.114.6.2  mjf static const struct db_command	*db_last_command = NULL;
    376  1.114.6.2  mjf #if defined(DDB_COMMANDONENTER)
    377  1.114.6.2  mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
    378  1.114.6.2  mjf #else /* defined(DDB_COMMANDONENTER) */
    379  1.114.6.2  mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
    380  1.114.6.2  mjf #endif /* defined(DDB_COMMANDONENTER) */
    381  1.114.6.2  mjf #define	DB_LINE_SEP	';'
    382  1.114.6.2  mjf 
    383  1.114.6.2  mjf /*
    384  1.114.6.2  mjf  * Utility routine - discard tokens through end-of-line.
    385  1.114.6.2  mjf  */
    386  1.114.6.2  mjf void
    387  1.114.6.2  mjf db_skip_to_eol(void)
    388  1.114.6.2  mjf {
    389  1.114.6.2  mjf 	int t;
    390  1.114.6.2  mjf 
    391  1.114.6.2  mjf 	do {
    392  1.114.6.2  mjf 		t = db_read_token();
    393  1.114.6.2  mjf 	} while (t != tEOL);
    394  1.114.6.2  mjf }
    395  1.114.6.2  mjf 
    396  1.114.6.2  mjf void
    397  1.114.6.2  mjf db_error(const char *s)
    398  1.114.6.2  mjf {
    399  1.114.6.2  mjf 
    400  1.114.6.2  mjf 	if (s)
    401  1.114.6.2  mjf 		db_printf("%s", s);
    402  1.114.6.2  mjf 	db_flush_lex();
    403  1.114.6.2  mjf 	longjmp(db_recover);
    404  1.114.6.2  mjf }
    405  1.114.6.2  mjf 
    406  1.114.6.2  mjf /*Execute commandlist after ddb start
    407  1.114.6.2  mjf  *This function goes through the command list created from commands and ';'
    408  1.114.6.2  mjf  */
    409  1.114.6.2  mjf 
    410  1.114.6.2  mjf static void
    411  1.114.6.2  mjf db_execute_commandlist(const char *cmdlist)
    412  1.114.6.2  mjf {
    413  1.114.6.2  mjf 	const char *cmd = cmdlist;
    414  1.114.6.2  mjf 	const struct db_command	*dummy = NULL;
    415  1.114.6.2  mjf 
    416  1.114.6.2  mjf 	while (*cmd != '\0') {
    417  1.114.6.2  mjf 		const char *ep = cmd;
    418  1.114.6.2  mjf 
    419  1.114.6.2  mjf 		while (*ep != '\0' && *ep != DB_LINE_SEP) {
    420  1.114.6.2  mjf 			ep++;
    421  1.114.6.2  mjf 		}
    422  1.114.6.2  mjf 		db_set_line(cmd, ep);
    423  1.114.6.2  mjf 		db_command(&dummy);
    424  1.114.6.2  mjf 		cmd = ep;
    425  1.114.6.2  mjf 		if (*cmd == DB_LINE_SEP) {
    426  1.114.6.2  mjf 			cmd++;
    427  1.114.6.2  mjf 		}
    428  1.114.6.2  mjf 	}
    429  1.114.6.2  mjf }
    430  1.114.6.2  mjf 
    431  1.114.6.2  mjf /*Initialize ddb command tables*/
    432  1.114.6.2  mjf void
    433  1.114.6.2  mjf db_init_commands(void)
    434  1.114.6.2  mjf {
    435  1.114.6.2  mjf 	static bool done = false;
    436  1.114.6.2  mjf 
    437  1.114.6.2  mjf 	if (done) return;
    438  1.114.6.2  mjf 	done = true;
    439  1.114.6.2  mjf 
    440  1.114.6.2  mjf 	/* register command tables */
    441  1.114.6.2  mjf 	(void)db_register_tbl_entry(DDB_BASE_CMD, &db_base_cmd_builtins);
    442  1.114.6.2  mjf #ifdef DB_MACHINE_COMMANDS
    443  1.114.6.2  mjf 	(void)db_register_tbl_entry(DDB_MACH_CMD, &db_mach_cmd_builtins);
    444  1.114.6.2  mjf #endif
    445  1.114.6.2  mjf 	(void)db_register_tbl_entry(DDB_SHOW_CMD, &db_show_cmd_builtins);
    446  1.114.6.2  mjf }
    447  1.114.6.2  mjf 
    448  1.114.6.2  mjf 
    449  1.114.6.2  mjf /*
    450  1.114.6.2  mjf  * Add command table to the specified list
    451  1.114.6.2  mjf  * Arg:
    452  1.114.6.2  mjf  * int type specifies type of command table DDB_SHOW_CMD|DDB_BASE_CMD|DDB_MAC_CMD
    453  1.114.6.2  mjf  * *cmd_tbl poiter to static allocated db_command table
    454  1.114.6.2  mjf  *
    455  1.114.6.2  mjf  *Command table must be NULL terminated array of struct db_command
    456  1.114.6.2  mjf  */
    457  1.114.6.2  mjf int
    458  1.114.6.2  mjf db_register_tbl(uint8_t type, const struct db_command *cmd_tbl)
    459  1.114.6.2  mjf {
    460  1.114.6.2  mjf 	struct db_cmd_tbl_en *list_ent;
    461  1.114.6.2  mjf 
    462  1.114.6.2  mjf 	if (cmd_tbl->name == 0)
    463  1.114.6.2  mjf 		/* empty list - ignore */
    464  1.114.6.2  mjf 		return 0;
    465  1.114.6.2  mjf 
    466  1.114.6.2  mjf 	/* force builtin commands to be registered first */
    467  1.114.6.2  mjf 	db_init_commands();
    468  1.114.6.2  mjf 
    469  1.114.6.2  mjf 	/* now create a list entry for this table */
    470  1.114.6.2  mjf 	list_ent = malloc(sizeof(struct db_cmd_tbl_en), M_TEMP, M_ZERO);
    471  1.114.6.2  mjf 	if (list_ent == NULL)
    472  1.114.6.2  mjf 		return ENOMEM;
    473  1.114.6.2  mjf 	list_ent->db_cmd=cmd_tbl;
    474  1.114.6.2  mjf 
    475  1.114.6.2  mjf 	/* and register it */
    476  1.114.6.2  mjf 	return db_register_tbl_entry(type, list_ent);
    477  1.114.6.2  mjf }
    478  1.114.6.2  mjf 
    479  1.114.6.2  mjf static int
    480  1.114.6.2  mjf db_register_tbl_entry(uint8_t type, struct db_cmd_tbl_en *list_ent)
    481  1.114.6.2  mjf {
    482  1.114.6.2  mjf 	struct db_cmd_tbl_en_head *list;
    483  1.114.6.2  mjf 
    484  1.114.6.2  mjf 	switch(type) {
    485  1.114.6.2  mjf 	case DDB_BASE_CMD:
    486  1.114.6.2  mjf 		list = &db_base_cmd_list;
    487  1.114.6.2  mjf 		break;
    488  1.114.6.2  mjf 	case DDB_SHOW_CMD:
    489  1.114.6.2  mjf 		list = &db_show_cmd_list;
    490  1.114.6.2  mjf 		break;
    491  1.114.6.2  mjf 	case DDB_MACH_CMD:
    492  1.114.6.2  mjf 		list = &db_mach_cmd_list;
    493  1.114.6.2  mjf 		break;
    494  1.114.6.2  mjf 	default:
    495  1.114.6.2  mjf 		return ENOENT;
    496  1.114.6.2  mjf 	}
    497  1.114.6.2  mjf 
    498  1.114.6.2  mjf 	TAILQ_INSERT_TAIL(list, list_ent, db_cmd_next);
    499  1.114.6.2  mjf 
    500  1.114.6.2  mjf 	return 0;
    501  1.114.6.2  mjf }
    502  1.114.6.2  mjf 
    503  1.114.6.2  mjf /*
    504  1.114.6.2  mjf  * Remove command table specified with db_cmd address == cmd_tbl
    505  1.114.6.2  mjf  */
    506  1.114.6.2  mjf int
    507  1.114.6.2  mjf db_unregister_tbl(uint8_t type,const struct db_command *cmd_tbl)
    508  1.114.6.2  mjf {
    509  1.114.6.2  mjf 	struct db_cmd_tbl_en *list_ent;
    510  1.114.6.2  mjf 	struct db_cmd_tbl_en_head *list;
    511  1.114.6.2  mjf 
    512  1.114.6.2  mjf 	/* find list on which the entry should live */
    513  1.114.6.2  mjf 	switch (type) {
    514  1.114.6.2  mjf 	case DDB_BASE_CMD:
    515  1.114.6.2  mjf 		list=&db_base_cmd_list;
    516  1.114.6.2  mjf 		break;
    517  1.114.6.2  mjf 	case DDB_SHOW_CMD:
    518  1.114.6.2  mjf 		list=&db_show_cmd_list;
    519  1.114.6.2  mjf 		break;
    520  1.114.6.2  mjf 	case DDB_MACH_CMD:
    521  1.114.6.2  mjf 		list=&db_mach_cmd_list;
    522  1.114.6.2  mjf 		break;
    523  1.114.6.2  mjf 	default:
    524  1.114.6.2  mjf 		return EINVAL;
    525  1.114.6.2  mjf 	}
    526  1.114.6.2  mjf 
    527  1.114.6.2  mjf 	TAILQ_FOREACH (list_ent,list,db_cmd_next) {
    528  1.114.6.2  mjf 		if (list_ent->db_cmd == cmd_tbl){
    529  1.114.6.2  mjf 			TAILQ_REMOVE(list,
    530  1.114.6.2  mjf 			    list_ent,db_cmd_next);
    531  1.114.6.2  mjf 			free(list_ent,M_TEMP);
    532  1.114.6.2  mjf 			return 0;
    533  1.114.6.2  mjf 		}
    534  1.114.6.2  mjf 	}
    535  1.114.6.2  mjf 	return ENOENT;
    536  1.114.6.3  mjf }
    537  1.114.6.2  mjf 
    538  1.114.6.2  mjf /*This function is called from machine trap code.*/
    539  1.114.6.2  mjf void
    540  1.114.6.2  mjf db_command_loop(void)
    541  1.114.6.2  mjf {
    542  1.114.6.3  mjf 
    543  1.114.6.2  mjf 	label_t	db_jmpbuf;
    544  1.114.6.2  mjf 	label_t	*savejmp;
    545  1.114.6.2  mjf 
    546  1.114.6.2  mjf 	/*
    547  1.114.6.2  mjf 	 * Initialize 'prev' and 'next' to dot.
    548  1.114.6.2  mjf 	 */
    549  1.114.6.2  mjf 	db_prev = db_dot;
    550  1.114.6.2  mjf 	db_next = db_dot;
    551  1.114.6.2  mjf 
    552  1.114.6.2  mjf 	db_cmd_loop_done = false;
    553  1.114.6.2  mjf 
    554  1.114.6.2  mjf 	/*Init default command tables add machine, base,
    555  1.114.6.2  mjf 	  show command tables to the list*/
    556  1.114.6.2  mjf 	db_init_commands();
    557  1.114.6.2  mjf 
    558  1.114.6.2  mjf 	/*save context for return from ddb*/
    559  1.114.6.2  mjf 	savejmp = db_recover;
    560  1.114.6.2  mjf 	db_recover = &db_jmpbuf;
    561  1.114.6.2  mjf 	(void) setjmp(&db_jmpbuf);
    562  1.114.6.2  mjf 
    563  1.114.6.2  mjf 	/*Execute default ddb start commands*/
    564  1.114.6.2  mjf 	db_execute_commandlist(db_cmd_on_enter);
    565  1.114.6.2  mjf 
    566  1.114.6.2  mjf 	(void) setjmp(&db_jmpbuf);
    567  1.114.6.2  mjf 	while (!db_cmd_loop_done) {
    568  1.114.6.2  mjf 		if (db_print_position() != 0)
    569  1.114.6.2  mjf 			db_printf("\n");
    570  1.114.6.2  mjf 		db_output_line = 0;
    571  1.114.6.2  mjf 
    572  1.114.6.2  mjf 
    573  1.114.6.2  mjf #ifdef MULTIPROCESSOR
    574  1.114.6.2  mjf 		db_printf("db{%ld}> ", (long)cpu_number());
    575  1.114.6.2  mjf #else
    576  1.114.6.2  mjf 		db_printf("db> ");
    577  1.114.6.2  mjf #endif
    578  1.114.6.2  mjf 		(void) db_read_line();
    579  1.114.6.2  mjf 
    580  1.114.6.2  mjf 		db_command(&db_last_command);
    581  1.114.6.2  mjf 	}
    582  1.114.6.2  mjf 
    583  1.114.6.2  mjf 	db_recover = savejmp;
    584  1.114.6.2  mjf }
    585  1.114.6.2  mjf 
    586  1.114.6.2  mjf /*
    587  1.114.6.2  mjf  * Search for command table for command prefix
    588  1.114.6.2  mjf  * ret: CMD_UNIQUE    -> completely matches command
    589  1.114.6.2  mjf  *      CMD_FOUND     -> matches prefix of single command
    590  1.114.6.2  mjf  *      CMD_AMBIGIOUS -> matches prefix of more than one command
    591  1.114.6.2  mjf  *      CMD_NONE      -> command not found
    592  1.114.6.2  mjf  */
    593  1.114.6.2  mjf static int
    594  1.114.6.2  mjf db_cmd_search(const char *name,const struct db_command *table,
    595  1.114.6.2  mjf     const struct db_command **cmdp)
    596  1.114.6.2  mjf {
    597  1.114.6.3  mjf 
    598  1.114.6.2  mjf 	const struct db_command	*cmd;
    599  1.114.6.2  mjf 	int result;
    600  1.114.6.2  mjf 
    601  1.114.6.2  mjf 	result = CMD_NONE;
    602  1.114.6.2  mjf 	*cmdp = NULL;
    603  1.114.6.2  mjf 	for (cmd = table; cmd->name != 0; cmd++) {
    604  1.114.6.2  mjf 		const char *lp;
    605  1.114.6.2  mjf 		const char *rp;
    606  1.114.6.2  mjf 
    607  1.114.6.2  mjf 		lp = name;
    608  1.114.6.2  mjf 		rp = cmd->name;
    609  1.114.6.2  mjf 		while (*lp != '\0' && *lp == *rp) {
    610  1.114.6.2  mjf 			rp++;
    611  1.114.6.2  mjf 			lp++;
    612  1.114.6.2  mjf 		}
    613  1.114.6.2  mjf 
    614  1.114.6.2  mjf 		if (*lp != '\0') /* mismatch or extra chars in name */
    615  1.114.6.2  mjf 			continue;
    616  1.114.6.2  mjf 
    617  1.114.6.2  mjf 		if (*rp == '\0') { /* complete match */
    618  1.114.6.2  mjf 			*cmdp = cmd;
    619  1.114.6.2  mjf 			return (CMD_UNIQUE);
    620  1.114.6.2  mjf 		}
    621  1.114.6.2  mjf 
    622  1.114.6.2  mjf 		/* prefix match: end of name, not end of command */
    623  1.114.6.2  mjf 		if (result == CMD_NONE) {
    624  1.114.6.2  mjf 			result = CMD_FOUND;
    625  1.114.6.2  mjf 			*cmdp = cmd;
    626  1.114.6.2  mjf 		}
    627  1.114.6.2  mjf 		else if (result == CMD_FOUND) {
    628  1.114.6.2  mjf 			result = CMD_AMBIGUOUS;
    629  1.114.6.2  mjf 			*cmdp = NULL;
    630  1.114.6.2  mjf 		}
    631  1.114.6.2  mjf 	}
    632  1.114.6.2  mjf 
    633  1.114.6.2  mjf 	return (result);
    634  1.114.6.2  mjf }
    635  1.114.6.2  mjf 
    636  1.114.6.2  mjf /*
    637  1.114.6.2  mjf  *List commands to the console.
    638  1.114.6.2  mjf  */
    639  1.114.6.2  mjf static void
    640  1.114.6.2  mjf db_cmd_list(const struct db_cmd_tbl_en_head *list)
    641  1.114.6.2  mjf {
    642  1.114.6.2  mjf 
    643  1.114.6.2  mjf 	struct db_cmd_tbl_en *list_ent;
    644  1.114.6.2  mjf 	const struct db_command *table;
    645  1.114.6.2  mjf 	size_t		i, j, w, columns, lines, numcmds, width=0;
    646  1.114.6.2  mjf 	const char	*p;
    647  1.114.6.2  mjf 
    648  1.114.6.2  mjf 	TAILQ_FOREACH(list_ent,list,db_cmd_next) {
    649  1.114.6.2  mjf 		table = list_ent->db_cmd;
    650  1.114.6.2  mjf 		for (i = 0; table[i].name != NULL; i++) {
    651  1.114.6.2  mjf 			w = strlen(table[i].name);
    652  1.114.6.2  mjf 			if (w > width)
    653  1.114.6.2  mjf 				width = w;
    654  1.114.6.2  mjf 		}
    655  1.114.6.2  mjf 	}
    656  1.114.6.2  mjf 
    657  1.114.6.2  mjf 	width = DB_NEXT_TAB(width);
    658  1.114.6.2  mjf 
    659  1.114.6.2  mjf 	columns = db_max_width / width;
    660  1.114.6.2  mjf 	if (columns == 0)
    661  1.114.6.2  mjf 		columns = 1;
    662  1.114.6.2  mjf 
    663  1.114.6.2  mjf 	TAILQ_FOREACH(list_ent,list,db_cmd_next) {
    664  1.114.6.2  mjf 		table = list_ent->db_cmd;
    665  1.114.6.2  mjf 
    666  1.114.6.2  mjf 		for (numcmds = 0; table[numcmds].name != NULL; numcmds++)
    667  1.114.6.2  mjf 			;
    668  1.114.6.2  mjf 		lines = (numcmds + columns - 1) / columns;
    669  1.114.6.3  mjf 
    670  1.114.6.2  mjf 		for (i = 0; i < lines; i++) {
    671  1.114.6.2  mjf 			for (j = 0; j < columns; j++) {
    672  1.114.6.2  mjf 				p = table[j * lines + i].name;
    673  1.114.6.2  mjf 				if (p)
    674  1.114.6.2  mjf 					db_printf("%s", p);
    675  1.114.6.2  mjf 				if (j * lines + i + lines >= numcmds) {
    676  1.114.6.2  mjf 					db_putchar('\n');
    677  1.114.6.2  mjf 					break;
    678  1.114.6.2  mjf 				}
    679  1.114.6.2  mjf 				if (p) {
    680  1.114.6.2  mjf 					w = strlen(p);
    681  1.114.6.2  mjf 					while (w < width) {
    682  1.114.6.2  mjf 						w = DB_NEXT_TAB(w);
    683  1.114.6.2  mjf 						db_putchar('\t');
    684  1.114.6.2  mjf 					}
    685  1.114.6.2  mjf 				}
    686  1.114.6.2  mjf 			}
    687  1.114.6.2  mjf 		}
    688  1.114.6.2  mjf 	}
    689  1.114.6.2  mjf 	return;
    690  1.114.6.2  mjf }
    691  1.114.6.2  mjf 
    692  1.114.6.2  mjf /*
    693  1.114.6.2  mjf  *Returns type of list for command with name *name.
    694  1.114.6.2  mjf  */
    695  1.114.6.2  mjf static int
    696  1.114.6.2  mjf db_get_list_type(const char *name)
    697  1.114.6.2  mjf {
    698  1.114.6.2  mjf 
    699  1.114.6.2  mjf 	const struct db_command    *cmd;
    700  1.114.6.2  mjf 	struct db_cmd_tbl_en *list_ent;
    701  1.114.6.2  mjf 	int error,ret=-1;
    702  1.114.6.2  mjf 
    703  1.114.6.2  mjf 	/* search for the command name */
    704  1.114.6.2  mjf 	TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next) {
    705  1.114.6.2  mjf 		/*
    706  1.114.6.2  mjf 		 * cmd_search returns CMD_UNIQUE, CMD_FOUND ...
    707  1.114.6.2  mjf 		 * CMD_UNIQUE when name was completly matched to cmd->name
    708  1.114.6.2  mjf 		 * CMD_FOUND  when name was only partially matched to cmd->name
    709  1.114.6.2  mjf 		 * CMD_NONE   command not found in a list
    710  1.114.6.2  mjf 		 * CMD_AMBIGIOUS ->more partialy matches
    711  1.114.6.2  mjf 		 */
    712  1.114.6.2  mjf 
    713  1.114.6.2  mjf 		error = db_cmd_search(name, list_ent->db_cmd, &cmd);
    714  1.114.6.2  mjf 
    715  1.114.6.2  mjf 		if (error == CMD_UNIQUE) {
    716  1.114.6.2  mjf 			/* exact match found */
    717  1.114.6.2  mjf 			if (cmd->flag == CS_SHOW) {
    718  1.114.6.2  mjf 				ret = DDB_SHOW_CMD;
    719  1.114.6.2  mjf 				break;
    720  1.114.6.2  mjf 			}
    721  1.114.6.2  mjf 			if (cmd->flag == CS_MACH) {
    722  1.114.6.2  mjf 				ret = DDB_MACH_CMD;
    723  1.114.6.2  mjf 				break;
    724  1.114.6.2  mjf 			} else {
    725  1.114.6.2  mjf 				ret = DDB_BASE_CMD;
    726  1.114.6.2  mjf 				break;
    727  1.114.6.2  mjf 			}
    728  1.114.6.2  mjf 
    729  1.114.6.2  mjf 		} else if (error == CMD_FOUND) {
    730  1.114.6.2  mjf 			/*
    731  1.114.6.2  mjf 			 * partial match, search will continue, but
    732  1.114.6.2  mjf 			 * note current result in case we won't
    733  1.114.6.2  mjf 			 * find anything better.
    734  1.114.6.2  mjf 			 */
    735  1.114.6.2  mjf 			if (cmd->flag == CS_SHOW)
    736  1.114.6.2  mjf 				ret = DDB_SHOW_CMD;
    737  1.114.6.2  mjf 			else if (cmd->flag == CS_MACH)
    738  1.114.6.2  mjf 				ret = DDB_MACH_CMD;
    739  1.114.6.2  mjf 			else
    740  1.114.6.2  mjf 				ret = DDB_BASE_CMD;
    741  1.114.6.2  mjf 		}
    742  1.114.6.2  mjf 	}
    743  1.114.6.2  mjf 
    744  1.114.6.2  mjf 	return ret;
    745  1.114.6.2  mjf }
    746  1.114.6.2  mjf 
    747  1.114.6.2  mjf /*
    748  1.114.6.2  mjf  *Parse command line and execute apropriate function.
    749  1.114.6.2  mjf  */
    750  1.114.6.2  mjf static void
    751  1.114.6.2  mjf db_command(const struct db_command **last_cmdp)
    752  1.114.6.2  mjf {
    753  1.114.6.2  mjf 	const struct db_command *command;
    754  1.114.6.2  mjf 	struct db_cmd_tbl_en *list_ent;
    755  1.114.6.2  mjf 	struct db_cmd_tbl_en_head *list;
    756  1.114.6.3  mjf 
    757  1.114.6.2  mjf 	int		t;
    758  1.114.6.2  mjf 	int		result;
    759  1.114.6.3  mjf 
    760  1.114.6.2  mjf 	char		modif[TOK_STRING_SIZE];
    761  1.114.6.2  mjf 	db_expr_t	addr, count;
    762  1.114.6.2  mjf 	bool		have_addr = false;
    763  1.114.6.2  mjf 
    764  1.114.6.2  mjf 	static db_expr_t last_count = 0;
    765  1.114.6.3  mjf 
    766  1.114.6.2  mjf 	command = NULL;	/* XXX gcc */
    767  1.114.6.2  mjf 
    768  1.114.6.2  mjf 	t = db_read_token();
    769  1.114.6.2  mjf 	if ((t == tEOL) || (t == tCOMMA)) {
    770  1.114.6.2  mjf 		/*
    771  1.114.6.2  mjf 		 * An empty line repeats last command, at 'next'.
    772  1.114.6.2  mjf 		 * Only a count repeats the last command with the new count.
    773  1.114.6.2  mjf 		 */
    774  1.114.6.2  mjf 		command = *last_cmdp;
    775  1.114.6.2  mjf 
    776  1.114.6.2  mjf 		if (!command)
    777  1.114.6.2  mjf 			return;
    778  1.114.6.2  mjf 
    779  1.114.6.2  mjf 		addr = (db_expr_t)db_next;
    780  1.114.6.2  mjf 		if (t == tCOMMA) {
    781  1.114.6.2  mjf 			if (!db_expression(&count)) {
    782  1.114.6.2  mjf 				db_printf("Count missing\n");
    783  1.114.6.2  mjf 				db_flush_lex();
    784  1.114.6.2  mjf 				return;
    785  1.114.6.2  mjf 			}
    786  1.114.6.2  mjf 		} else
    787  1.114.6.2  mjf 			count = last_count;
    788  1.114.6.2  mjf 		have_addr = false;
    789  1.114.6.2  mjf 		modif[0] = '\0';
    790  1.114.6.2  mjf 		db_skip_to_eol();
    791  1.114.6.2  mjf 
    792  1.114.6.2  mjf 	} else if (t == tEXCL) {
    793  1.114.6.2  mjf 		db_fncall(0, 0, 0, NULL);
    794  1.114.6.2  mjf 		return;
    795  1.114.6.2  mjf 
    796  1.114.6.2  mjf 	} else if (t != tIDENT) {
    797  1.114.6.2  mjf 		db_printf("?\n");
    798  1.114.6.2  mjf 		db_flush_lex();
    799  1.114.6.2  mjf 		return;
    800  1.114.6.2  mjf 
    801  1.114.6.2  mjf 	} else {
    802  1.114.6.2  mjf 
    803  1.114.6.2  mjf 		switch(db_get_list_type(db_tok_string)) {
    804  1.114.6.2  mjf 
    805  1.114.6.2  mjf 		case DDB_BASE_CMD:
    806  1.114.6.2  mjf 			list = &db_base_cmd_list;
    807  1.114.6.2  mjf 			break;
    808  1.114.6.2  mjf 
    809  1.114.6.2  mjf 		case DDB_SHOW_CMD:
    810  1.114.6.2  mjf 			list = &db_show_cmd_list;
    811  1.114.6.2  mjf 			/* need to read show subcommand if show command list
    812  1.114.6.2  mjf 			   is used. */
    813  1.114.6.2  mjf 			t = db_read_token();
    814  1.114.6.2  mjf 
    815  1.114.6.2  mjf 			if (t != tIDENT) {
    816  1.114.6.2  mjf 				/* if only show command is executed, print
    817  1.114.6.2  mjf 				   all subcommands */
    818  1.114.6.3  mjf 				db_cmd_list(list);
    819  1.114.6.2  mjf 				db_flush_lex();
    820  1.114.6.2  mjf 				return;
    821  1.114.6.2  mjf 			}
    822  1.114.6.2  mjf 			break;
    823  1.114.6.2  mjf 		case DDB_MACH_CMD:
    824  1.114.6.2  mjf 			list = &db_mach_cmd_list;
    825  1.114.6.2  mjf 			/* need to read machine subcommand if
    826  1.114.6.2  mjf 			  machine level 2 command list is used. */
    827  1.114.6.2  mjf 			t = db_read_token();
    828  1.114.6.2  mjf 
    829  1.114.6.2  mjf 			if (t != tIDENT) {
    830  1.114.6.2  mjf 				/* if only show command is executed, print
    831  1.114.6.2  mjf 				   all subcommands */
    832  1.114.6.2  mjf 				db_cmd_list(list);
    833  1.114.6.2  mjf 				db_flush_lex();
    834  1.114.6.2  mjf 				return;
    835  1.114.6.3  mjf 			}
    836  1.114.6.2  mjf 			break;
    837  1.114.6.2  mjf 		default:
    838  1.114.6.2  mjf 			db_printf("No such command\n");
    839  1.114.6.3  mjf 			db_flush_lex();
    840  1.114.6.2  mjf 			return;
    841  1.114.6.2  mjf 		}
    842  1.114.6.2  mjf 
    843  1.114.6.2  mjf  COMPAT_RET:
    844  1.114.6.2  mjf 		TAILQ_FOREACH(list_ent, list, db_cmd_next) {
    845  1.114.6.2  mjf 			result = db_cmd_search(db_tok_string, list_ent->db_cmd,
    846  1.114.6.2  mjf 			    &command);
    847  1.114.6.2  mjf 
    848  1.114.6.2  mjf 			/* after CMD_UNIQUE in cmd_list only a single command
    849  1.114.6.2  mjf 			   name is possible */
    850  1.114.6.2  mjf 			if (result == CMD_UNIQUE)
    851  1.114.6.2  mjf 				break;
    852  1.114.6.2  mjf 
    853  1.114.6.2  mjf 		}
    854  1.114.6.2  mjf 
    855  1.114.6.3  mjf 		/* check compatibility flag */
    856  1.114.6.2  mjf 		if (command && command->flag & CS_COMPAT){
    857  1.114.6.2  mjf 			t = db_read_token();
    858  1.114.6.2  mjf 			if (t != tIDENT) {
    859  1.114.6.2  mjf 					db_cmd_list(list);
    860  1.114.6.2  mjf 					db_flush_lex();
    861  1.114.6.2  mjf 					return;
    862  1.114.6.2  mjf 			}
    863  1.114.6.2  mjf 
    864  1.114.6.2  mjf 			/* support only level 2 commands here */
    865  1.114.6.2  mjf 			goto COMPAT_RET;
    866  1.114.6.2  mjf 		}
    867  1.114.6.2  mjf 
    868  1.114.6.2  mjf 		if (!command) {
    869  1.114.6.2  mjf 			db_printf("No such command\n");
    870  1.114.6.2  mjf 			db_flush_lex();
    871  1.114.6.2  mjf 			return;
    872  1.114.6.2  mjf 		}
    873  1.114.6.2  mjf 
    874  1.114.6.2  mjf 		if ((command->flag & CS_OWN) == 0) {
    875  1.114.6.2  mjf 
    876  1.114.6.2  mjf 			/*
    877  1.114.6.2  mjf 			 * Standard syntax:
    878  1.114.6.2  mjf 			 * command [/modifier] [addr] [,count]
    879  1.114.6.2  mjf 			 */
    880  1.114.6.2  mjf 			t = db_read_token(); /* get modifier */
    881  1.114.6.3  mjf 			if (t == tSLASH) {
    882  1.114.6.2  mjf 				t = db_read_token();
    883  1.114.6.2  mjf 				if (t != tIDENT) {
    884  1.114.6.2  mjf 					db_printf("Bad modifier\n");
    885  1.114.6.2  mjf 					db_flush_lex();
    886  1.114.6.2  mjf 					return;
    887  1.114.6.2  mjf 				}
    888  1.114.6.2  mjf 				/* save modifier */
    889  1.114.6.2  mjf 				strlcpy(modif, db_tok_string, sizeof(modif));
    890  1.114.6.3  mjf 
    891  1.114.6.2  mjf 			} else {
    892  1.114.6.2  mjf 				db_unread_token(t);
    893  1.114.6.2  mjf 				modif[0] = '\0';
    894  1.114.6.2  mjf 			}
    895  1.114.6.2  mjf 
    896  1.114.6.2  mjf 			if (db_expression(&addr)) { /*get address*/
    897  1.114.6.2  mjf 				db_dot = (db_addr_t) addr;
    898  1.114.6.2  mjf 				db_last_addr = db_dot;
    899  1.114.6.2  mjf 				have_addr = true;
    900  1.114.6.2  mjf 			} else {
    901  1.114.6.2  mjf 				addr = (db_expr_t) db_dot;
    902  1.114.6.2  mjf 				have_addr = false;
    903  1.114.6.2  mjf 			}
    904  1.114.6.2  mjf 
    905  1.114.6.2  mjf 			t = db_read_token();
    906  1.114.6.2  mjf 			if (t == tCOMMA) { /*Get count*/
    907  1.114.6.2  mjf 				if (!db_expression(&count)) {
    908  1.114.6.2  mjf 					db_printf("Count missing\n");
    909  1.114.6.2  mjf 					db_flush_lex();
    910  1.114.6.2  mjf 					return;
    911  1.114.6.2  mjf 				}
    912  1.114.6.3  mjf 			} else {
    913  1.114.6.2  mjf 				db_unread_token(t);
    914  1.114.6.2  mjf 				count = -1;
    915  1.114.6.2  mjf 			}
    916  1.114.6.2  mjf 			if ((command->flag & CS_MORE) == 0) {
    917  1.114.6.2  mjf 				db_skip_to_eol();
    918  1.114.6.2  mjf 			}
    919  1.114.6.2  mjf 		}
    920  1.114.6.2  mjf 	}
    921  1.114.6.2  mjf 
    922  1.114.6.2  mjf 	if (command->flag & CS_NOREPEAT) {
    923  1.114.6.2  mjf 		*last_cmdp = NULL;
    924  1.114.6.2  mjf 		last_count = 0;
    925  1.114.6.2  mjf 	} else {
    926  1.114.6.2  mjf 		*last_cmdp = command;
    927  1.114.6.2  mjf 		last_count = count;
    928  1.114.6.2  mjf 	}
    929  1.114.6.2  mjf 
    930  1.114.6.2  mjf 	if (command != NULL) {
    931  1.114.6.2  mjf 		/*
    932  1.114.6.2  mjf 		 * Execute the command.
    933  1.114.6.2  mjf 		 */
    934  1.114.6.2  mjf 		if (command->fcn != NULL)
    935  1.114.6.2  mjf 			(*command->fcn)(addr, have_addr, count, modif);
    936  1.114.6.2  mjf 
    937  1.114.6.2  mjf 		if (command->flag & CS_SET_DOT) {
    938  1.114.6.2  mjf 			/*
    939  1.114.6.2  mjf 			 * If command changes dot, set dot to
    940  1.114.6.2  mjf 			 * previous address displayed (if 'ed' style).
    941  1.114.6.2  mjf 			 */
    942  1.114.6.2  mjf 			if (db_ed_style)
    943  1.114.6.2  mjf 				db_dot = db_prev;
    944  1.114.6.2  mjf 			else
    945  1.114.6.2  mjf 				db_dot = db_next;
    946  1.114.6.2  mjf 		} else {
    947  1.114.6.2  mjf 			/*
    948  1.114.6.2  mjf 			 * If command does not change dot,
    949  1.114.6.2  mjf 			 * set 'next' location to be the same.
    950  1.114.6.2  mjf 			 */
    951  1.114.6.2  mjf 			db_next = db_dot;
    952  1.114.6.2  mjf 		}
    953  1.114.6.2  mjf 	}
    954  1.114.6.2  mjf }
    955  1.114.6.2  mjf 
    956  1.114.6.2  mjf /*
    957  1.114.6.2  mjf  * Print help for commands
    958  1.114.6.2  mjf  */
    959  1.114.6.2  mjf static void
    960  1.114.6.2  mjf db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
    961  1.114.6.2  mjf     const char *modif)
    962  1.114.6.2  mjf {
    963  1.114.6.3  mjf 
    964  1.114.6.2  mjf 	const struct db_cmd_tbl_en_head *list;
    965  1.114.6.2  mjf 	const struct db_cmd_tbl_en *list_ent;
    966  1.114.6.2  mjf 	const struct db_command *help = NULL;
    967  1.114.6.2  mjf 	int t, result;
    968  1.114.6.3  mjf 
    969  1.114.6.2  mjf 	t = db_read_token();
    970  1.114.6.2  mjf 	/* is there another command after the "help"? */
    971  1.114.6.2  mjf 	if (t == tIDENT){
    972  1.114.6.2  mjf 
    973  1.114.6.2  mjf 		switch(db_get_list_type(db_tok_string)) {
    974  1.114.6.2  mjf 
    975  1.114.6.2  mjf 		case DDB_BASE_CMD:
    976  1.114.6.2  mjf 			list=&db_base_cmd_list;
    977  1.114.6.2  mjf 			break;
    978  1.114.6.2  mjf 		case DDB_SHOW_CMD:
    979  1.114.6.2  mjf 			list=&db_show_cmd_list;
    980  1.114.6.2  mjf 			/* read the show subcommand */
    981  1.114.6.3  mjf 			t = db_read_token();
    982  1.114.6.2  mjf 
    983  1.114.6.2  mjf 			if (t != tIDENT) {
    984  1.114.6.2  mjf 				/* no subcommand, print the list */
    985  1.114.6.2  mjf 				db_cmd_list(list);
    986  1.114.6.2  mjf 				db_flush_lex();
    987  1.114.6.2  mjf 				return;
    988  1.114.6.3  mjf 			}
    989  1.114.6.3  mjf 
    990  1.114.6.2  mjf 			break;
    991  1.114.6.2  mjf 		case DDB_MACH_CMD:
    992  1.114.6.2  mjf 			list=&db_mach_cmd_list;
    993  1.114.6.2  mjf 			/* read machine subcommand */
    994  1.114.6.3  mjf 			t = db_read_token();
    995  1.114.6.2  mjf 
    996  1.114.6.2  mjf 			if (t != tIDENT) {
    997  1.114.6.2  mjf 				/* no subcommand - just print the list */
    998  1.114.6.2  mjf 				db_cmd_list(list);
    999  1.114.6.2  mjf 				db_flush_lex();
   1000  1.114.6.2  mjf 				return;
   1001  1.114.6.2  mjf 			}
   1002  1.114.6.2  mjf 			break;
   1003  1.114.6.2  mjf 
   1004  1.114.6.2  mjf 		default:
   1005  1.114.6.2  mjf 			db_printf("No such command\n");
   1006  1.114.6.2  mjf 			db_flush_lex();
   1007  1.114.6.2  mjf 			return;
   1008  1.114.6.2  mjf 		}
   1009  1.114.6.3  mjf  COMPAT_RET:
   1010  1.114.6.2  mjf 		TAILQ_FOREACH(list_ent,list,db_cmd_next){
   1011  1.114.6.2  mjf 			result = db_cmd_search(db_tok_string, list_ent->db_cmd,
   1012  1.114.6.2  mjf 					&help);
   1013  1.114.6.2  mjf 			/* after CMD_UNIQUE only a single command
   1014  1.114.6.2  mjf 			   name is possible */
   1015  1.114.6.2  mjf 			if (result == CMD_UNIQUE)
   1016  1.114.6.2  mjf 				break;
   1017  1.114.6.2  mjf 		}
   1018  1.114.6.2  mjf #ifdef DDB_VERBOSE_HELP
   1019  1.114.6.2  mjf 		/*print help*/
   1020  1.114.6.2  mjf 
   1021  1.114.6.2  mjf 		db_printf("Command: %s\n",help->name);
   1022  1.114.6.2  mjf 
   1023  1.114.6.2  mjf 		if (help->cmd_descr != NULL)
   1024  1.114.6.2  mjf 			db_printf(" Description: %s\n",help->cmd_descr);
   1025  1.114.6.3  mjf 
   1026  1.114.6.2  mjf 		if (help->cmd_arg != NULL)
   1027  1.114.6.2  mjf 			db_printf(" Arguments: %s\n",help->cmd_arg);
   1028  1.114.6.2  mjf 
   1029  1.114.6.2  mjf 		if (help->cmd_arg_help != NULL)
   1030  1.114.6.2  mjf 			db_printf(" Arguments description:\n%s\n",
   1031  1.114.6.2  mjf 			    help->cmd_arg_help);
   1032  1.114.6.2  mjf 
   1033  1.114.6.2  mjf 		if ((help->cmd_arg == NULL) && (help->cmd_descr == NULL))
   1034  1.114.6.2  mjf 			db_printf("%s Doesn't have any help message included.\n",
   1035  1.114.6.2  mjf 			    help->name);
   1036  1.114.6.2  mjf #endif
   1037  1.114.6.2  mjf 		/* check compatibility flag */
   1038  1.114.6.2  mjf 		/*
   1039  1.114.6.2  mjf 		 * The "show all" command table has been merged with the
   1040  1.114.6.2  mjf 		 * "show" command table - but we want to keep the old UI
   1041  1.114.6.2  mjf 		 * available. So if we find a CS_COMPAT entry, we read
   1042  1.114.6.2  mjf 		 * the next token and try again.
   1043  1.114.6.2  mjf 		 */
   1044  1.114.6.2  mjf 		if (help->flag == CS_COMPAT){
   1045  1.114.6.2  mjf 			t = db_read_token();
   1046  1.114.6.2  mjf 
   1047  1.114.6.2  mjf 			if (t != tIDENT){
   1048  1.114.6.2  mjf 				db_cmd_list(list);
   1049  1.114.6.2  mjf 				db_flush_lex();
   1050  1.114.6.2  mjf 				return;
   1051  1.114.6.2  mjf 			}
   1052  1.114.6.2  mjf 
   1053  1.114.6.2  mjf 			goto COMPAT_RET;
   1054  1.114.6.2  mjf 			/* support only level 2 commands here */
   1055  1.114.6.2  mjf 		} else {
   1056  1.114.6.2  mjf 			db_skip_to_eol();
   1057  1.114.6.2  mjf 		}
   1058  1.114.6.3  mjf 
   1059  1.114.6.2  mjf 	} else /* t != tIDENT */
   1060  1.114.6.2  mjf 		/* print base commands */
   1061  1.114.6.2  mjf 		db_cmd_list(&db_base_cmd_list);
   1062  1.114.6.3  mjf 
   1063  1.114.6.2  mjf 	return;
   1064  1.114.6.2  mjf }
   1065  1.114.6.2  mjf 
   1066  1.114.6.2  mjf /*ARGSUSED*/
   1067  1.114.6.2  mjf static void
   1068  1.114.6.2  mjf db_map_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
   1069  1.114.6.2  mjf     const char *modif)
   1070  1.114.6.2  mjf {
   1071  1.114.6.2  mjf 	bool full = false;
   1072  1.114.6.2  mjf 
   1073  1.114.6.2  mjf 	if (modif[0] == 'f')
   1074  1.114.6.2  mjf 		full = true;
   1075  1.114.6.2  mjf 
   1076  1.114.6.2  mjf 	if (have_addr == false)
   1077  1.114.6.4  mjf 		addr = (db_expr_t)(uintptr_t) kernel_map;
   1078  1.114.6.2  mjf 
   1079  1.114.6.4  mjf 	uvm_map_printit((struct vm_map *)(uintptr_t) addr, full, db_printf);
   1080  1.114.6.2  mjf }
   1081  1.114.6.2  mjf 
   1082  1.114.6.2  mjf /*ARGSUSED*/
   1083  1.114.6.2  mjf static void
   1084  1.114.6.2  mjf db_malloc_print_cmd(db_expr_t addr, bool have_addr,
   1085  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1086  1.114.6.2  mjf {
   1087  1.114.6.2  mjf 
   1088  1.114.6.2  mjf #ifdef MALLOC_DEBUG
   1089  1.114.6.2  mjf 	if (!have_addr)
   1090  1.114.6.2  mjf 		addr = 0;
   1091  1.114.6.2  mjf 
   1092  1.114.6.2  mjf 	debug_malloc_printit(db_printf, (vaddr_t) addr);
   1093  1.114.6.2  mjf #else
   1094  1.114.6.2  mjf 	db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
   1095  1.114.6.2  mjf #endif /* MALLOC_DEBUG */
   1096  1.114.6.2  mjf }
   1097  1.114.6.2  mjf 
   1098  1.114.6.2  mjf /*ARGSUSED*/
   1099  1.114.6.2  mjf static void
   1100  1.114.6.2  mjf db_object_print_cmd(db_expr_t addr, bool have_addr,
   1101  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1102  1.114.6.2  mjf {
   1103  1.114.6.2  mjf 	bool full = false;
   1104  1.114.6.2  mjf 
   1105  1.114.6.2  mjf 	if (modif[0] == 'f')
   1106  1.114.6.2  mjf 		full = true;
   1107  1.114.6.2  mjf 
   1108  1.114.6.4  mjf 	uvm_object_printit((struct uvm_object *)(uintptr_t) addr, full,
   1109  1.114.6.2  mjf 	    db_printf);
   1110  1.114.6.2  mjf }
   1111  1.114.6.2  mjf 
   1112  1.114.6.2  mjf /*ARGSUSED*/
   1113  1.114.6.2  mjf static void
   1114  1.114.6.2  mjf db_page_print_cmd(db_expr_t addr, bool have_addr,
   1115  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1116  1.114.6.2  mjf {
   1117  1.114.6.2  mjf 	bool full = false;
   1118  1.114.6.2  mjf 
   1119  1.114.6.2  mjf 	if (modif[0] == 'f')
   1120  1.114.6.2  mjf 		full = true;
   1121  1.114.6.2  mjf 
   1122  1.114.6.4  mjf 	uvm_page_printit((struct vm_page *)(uintptr_t) addr, full, db_printf);
   1123  1.114.6.2  mjf }
   1124  1.114.6.2  mjf 
   1125  1.114.6.2  mjf /*ARGSUSED*/
   1126  1.114.6.2  mjf static void
   1127  1.114.6.2  mjf db_show_all_pages(db_expr_t addr, bool have_addr,
   1128  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1129  1.114.6.2  mjf {
   1130  1.114.6.2  mjf 
   1131  1.114.6.2  mjf 	uvm_page_printall(db_printf);
   1132  1.114.6.2  mjf }
   1133  1.114.6.2  mjf 
   1134  1.114.6.2  mjf /*ARGSUSED*/
   1135  1.114.6.2  mjf static void
   1136  1.114.6.2  mjf db_buf_print_cmd(db_expr_t addr, bool have_addr,
   1137  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1138  1.114.6.2  mjf {
   1139  1.114.6.2  mjf 	bool full = false;
   1140  1.114.6.2  mjf 
   1141  1.114.6.2  mjf 	if (modif[0] == 'f')
   1142  1.114.6.2  mjf 		full = true;
   1143  1.114.6.2  mjf 
   1144  1.114.6.4  mjf 	vfs_buf_print((struct buf *)(uintptr_t) addr, full, db_printf);
   1145  1.114.6.2  mjf }
   1146  1.114.6.2  mjf 
   1147  1.114.6.2  mjf /*ARGSUSED*/
   1148  1.114.6.2  mjf static void
   1149  1.114.6.2  mjf db_event_print_cmd(db_expr_t addr, bool have_addr,
   1150  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1151  1.114.6.2  mjf {
   1152  1.114.6.2  mjf 	bool full = false;
   1153  1.114.6.2  mjf 
   1154  1.114.6.2  mjf 	if (modif[0] == 'f')
   1155  1.114.6.2  mjf 		full = true;
   1156  1.114.6.2  mjf 
   1157  1.114.6.2  mjf 	event_print(full, db_printf);
   1158  1.114.6.2  mjf }
   1159  1.114.6.2  mjf 
   1160  1.114.6.2  mjf /*ARGSUSED*/
   1161  1.114.6.2  mjf static void
   1162  1.114.6.2  mjf db_vnode_print_cmd(db_expr_t addr, bool have_addr,
   1163  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1164  1.114.6.2  mjf {
   1165  1.114.6.2  mjf 	bool full = false;
   1166  1.114.6.2  mjf 
   1167  1.114.6.2  mjf 	if (modif[0] == 'f')
   1168  1.114.6.2  mjf 		full = true;
   1169  1.114.6.2  mjf 
   1170  1.114.6.4  mjf 	vfs_vnode_print((struct vnode *)(uintptr_t) addr, full, db_printf);
   1171  1.114.6.2  mjf }
   1172  1.114.6.2  mjf 
   1173  1.114.6.2  mjf static void
   1174  1.114.6.2  mjf db_mount_print_cmd(db_expr_t addr, bool have_addr,
   1175  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1176  1.114.6.2  mjf {
   1177  1.114.6.2  mjf 	bool full = false;
   1178  1.114.6.2  mjf 
   1179  1.114.6.2  mjf 	if (modif[0] == 'f')
   1180  1.114.6.2  mjf 		full = true;
   1181  1.114.6.2  mjf 
   1182  1.114.6.4  mjf 	vfs_mount_print((struct mount *)(uintptr_t) addr, full, db_printf);
   1183  1.114.6.2  mjf }
   1184  1.114.6.2  mjf 
   1185  1.114.6.2  mjf /*ARGSUSED*/
   1186  1.114.6.2  mjf static void
   1187  1.114.6.2  mjf db_mbuf_print_cmd(db_expr_t addr, bool have_addr,
   1188  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1189  1.114.6.2  mjf {
   1190  1.114.6.2  mjf 
   1191  1.114.6.4  mjf 	m_print((const struct mbuf *)(uintptr_t) addr, modif, db_printf);
   1192  1.114.6.2  mjf }
   1193  1.114.6.2  mjf 
   1194  1.114.6.2  mjf /*ARGSUSED*/
   1195  1.114.6.2  mjf static void
   1196  1.114.6.2  mjf db_pool_print_cmd(db_expr_t addr, bool have_addr,
   1197  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1198  1.114.6.2  mjf {
   1199  1.114.6.2  mjf 
   1200  1.114.6.4  mjf 	pool_printit((struct pool *)(uintptr_t) addr, modif, db_printf);
   1201  1.114.6.2  mjf }
   1202  1.114.6.2  mjf 
   1203  1.114.6.2  mjf /*ARGSUSED*/
   1204  1.114.6.2  mjf static void
   1205  1.114.6.2  mjf db_namecache_print_cmd(db_expr_t addr, bool have_addr,
   1206  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1207  1.114.6.2  mjf {
   1208  1.114.6.2  mjf 
   1209  1.114.6.4  mjf 	namecache_print((struct vnode *)(uintptr_t) addr, db_printf);
   1210  1.114.6.2  mjf }
   1211  1.114.6.2  mjf 
   1212  1.114.6.2  mjf /*ARGSUSED*/
   1213  1.114.6.2  mjf static void
   1214  1.114.6.2  mjf db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
   1215  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1216  1.114.6.2  mjf {
   1217  1.114.6.2  mjf 
   1218  1.114.6.2  mjf 	uvmexp_print(db_printf);
   1219  1.114.6.2  mjf }
   1220  1.114.6.2  mjf 
   1221  1.114.6.3  mjf #ifdef UVMHIST
   1222  1.114.6.3  mjf /*ARGSUSED*/
   1223  1.114.6.3  mjf static void
   1224  1.114.6.3  mjf db_uvmhist_print_cmd(db_expr_t addr, bool have_addr,
   1225  1.114.6.3  mjf     db_expr_t count, const char *modif)
   1226  1.114.6.3  mjf {
   1227  1.114.6.3  mjf 
   1228  1.114.6.3  mjf 	uvmhist_print(db_printf);
   1229  1.114.6.3  mjf }
   1230  1.114.6.3  mjf #endif
   1231  1.114.6.3  mjf 
   1232  1.114.6.2  mjf /*ARGSUSED*/
   1233  1.114.6.2  mjf static void
   1234  1.114.6.2  mjf db_lock_print_cmd(db_expr_t addr, bool have_addr,
   1235  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1236  1.114.6.2  mjf {
   1237  1.114.6.2  mjf 
   1238  1.114.6.2  mjf 	lockdebug_lock_print((void *)addr, db_printf);
   1239  1.114.6.2  mjf }
   1240  1.114.6.2  mjf 
   1241  1.114.6.2  mjf /*
   1242  1.114.6.2  mjf  * Call random function:
   1243  1.114.6.2  mjf  * !expr(arg,arg,arg)
   1244  1.114.6.2  mjf  */
   1245  1.114.6.2  mjf /*ARGSUSED*/
   1246  1.114.6.2  mjf static void
   1247  1.114.6.2  mjf db_fncall(db_expr_t addr, bool have_addr,
   1248  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1249  1.114.6.2  mjf {
   1250  1.114.6.2  mjf 	db_expr_t	fn_addr;
   1251  1.114.6.2  mjf #define	MAXARGS		11
   1252  1.114.6.2  mjf 	db_expr_t	args[MAXARGS];
   1253  1.114.6.2  mjf 	int		nargs = 0;
   1254  1.114.6.2  mjf 	db_expr_t	retval;
   1255  1.114.6.2  mjf 	db_expr_t	(*func)(db_expr_t, ...);
   1256  1.114.6.2  mjf 	int		t;
   1257  1.114.6.2  mjf 
   1258  1.114.6.2  mjf 	if (!db_expression(&fn_addr)) {
   1259  1.114.6.2  mjf 		db_printf("Bad function\n");
   1260  1.114.6.2  mjf 		db_flush_lex();
   1261  1.114.6.2  mjf 		return;
   1262  1.114.6.2  mjf 	}
   1263  1.114.6.4  mjf 	func = (db_expr_t (*)(db_expr_t, ...))(uintptr_t) fn_addr;
   1264  1.114.6.2  mjf 
   1265  1.114.6.2  mjf 	t = db_read_token();
   1266  1.114.6.2  mjf 	if (t == tLPAREN) {
   1267  1.114.6.2  mjf 		if (db_expression(&args[0])) {
   1268  1.114.6.2  mjf 			nargs++;
   1269  1.114.6.2  mjf 			while ((t = db_read_token()) == tCOMMA) {
   1270  1.114.6.2  mjf 				if (nargs == MAXARGS) {
   1271  1.114.6.2  mjf 					db_printf("Too many arguments\n");
   1272  1.114.6.2  mjf 					db_flush_lex();
   1273  1.114.6.2  mjf 					return;
   1274  1.114.6.2  mjf 				}
   1275  1.114.6.2  mjf 				if (!db_expression(&args[nargs])) {
   1276  1.114.6.2  mjf 					db_printf("Argument missing\n");
   1277  1.114.6.2  mjf 					db_flush_lex();
   1278  1.114.6.2  mjf 					return;
   1279  1.114.6.2  mjf 				}
   1280  1.114.6.2  mjf 				nargs++;
   1281  1.114.6.2  mjf 			}
   1282  1.114.6.2  mjf 			db_unread_token(t);
   1283  1.114.6.2  mjf 		}
   1284  1.114.6.2  mjf 		if (db_read_token() != tRPAREN) {
   1285  1.114.6.2  mjf 			db_printf("?\n");
   1286  1.114.6.2  mjf 			db_flush_lex();
   1287  1.114.6.2  mjf 			return;
   1288  1.114.6.2  mjf 		}
   1289  1.114.6.2  mjf 	}
   1290  1.114.6.2  mjf 	db_skip_to_eol();
   1291  1.114.6.2  mjf 
   1292  1.114.6.2  mjf 	while (nargs < MAXARGS) {
   1293  1.114.6.2  mjf 		args[nargs++] = 0;
   1294  1.114.6.2  mjf 	}
   1295  1.114.6.2  mjf 
   1296  1.114.6.2  mjf 	retval = (*func)(args[0], args[1], args[2], args[3], args[4],
   1297  1.114.6.2  mjf 			 args[5], args[6], args[7], args[8], args[9]);
   1298  1.114.6.2  mjf 	db_printf("%s\n", db_num_to_str(retval));
   1299  1.114.6.2  mjf }
   1300  1.114.6.2  mjf 
   1301  1.114.6.2  mjf static void
   1302  1.114.6.2  mjf db_reboot_cmd(db_expr_t addr, bool have_addr,
   1303  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1304  1.114.6.2  mjf {
   1305  1.114.6.2  mjf 	db_expr_t bootflags;
   1306  1.114.6.2  mjf 
   1307  1.114.6.2  mjf 	/* Flags, default to RB_AUTOBOOT */
   1308  1.114.6.2  mjf 	if (!db_expression(&bootflags))
   1309  1.114.6.2  mjf 		bootflags = (db_expr_t)RB_AUTOBOOT;
   1310  1.114.6.2  mjf 	if (db_read_token() != tEOL) {
   1311  1.114.6.2  mjf 		db_error("?\n");
   1312  1.114.6.2  mjf 		/*NOTREACHED*/
   1313  1.114.6.2  mjf 	}
   1314  1.114.6.2  mjf 	/*
   1315  1.114.6.2  mjf 	 * We are leaving DDB, never to return upward.
   1316  1.114.6.2  mjf 	 * Clear db_recover so that we can debug faults in functions
   1317  1.114.6.2  mjf 	 * called from cpu_reboot.
   1318  1.114.6.2  mjf 	 */
   1319  1.114.6.2  mjf 	db_recover = 0;
   1320  1.114.6.2  mjf 	cpu_reboot((int)bootflags, NULL);
   1321  1.114.6.2  mjf }
   1322  1.114.6.2  mjf 
   1323  1.114.6.2  mjf static void
   1324  1.114.6.2  mjf db_sifting_cmd(db_expr_t addr, bool have_addr,
   1325  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1326  1.114.6.2  mjf {
   1327  1.114.6.2  mjf 	int	mode, t;
   1328  1.114.6.2  mjf 
   1329  1.114.6.2  mjf 	t = db_read_token();
   1330  1.114.6.2  mjf 	if (t == tSLASH) {
   1331  1.114.6.2  mjf 		t = db_read_token();
   1332  1.114.6.2  mjf 		if (t != tIDENT) {
   1333  1.114.6.2  mjf 			bad_modifier:
   1334  1.114.6.2  mjf 			db_printf("Bad modifier\n");
   1335  1.114.6.2  mjf 			db_flush_lex();
   1336  1.114.6.2  mjf 			return;
   1337  1.114.6.2  mjf 		}
   1338  1.114.6.2  mjf 		if (!strcmp(db_tok_string, "F"))
   1339  1.114.6.2  mjf 			mode = 'F';
   1340  1.114.6.2  mjf 		else
   1341  1.114.6.2  mjf 			goto bad_modifier;
   1342  1.114.6.2  mjf 		t = db_read_token();
   1343  1.114.6.2  mjf 	} else
   1344  1.114.6.2  mjf 		mode = 0;
   1345  1.114.6.2  mjf 
   1346  1.114.6.2  mjf 	if (t == tIDENT)
   1347  1.114.6.2  mjf 		db_sifting(db_tok_string, mode);
   1348  1.114.6.2  mjf 	else {
   1349  1.114.6.2  mjf 		db_printf("Bad argument (non-string)\n");
   1350  1.114.6.2  mjf 		db_flush_lex();
   1351  1.114.6.2  mjf 	}
   1352  1.114.6.2  mjf }
   1353  1.114.6.2  mjf 
   1354  1.114.6.2  mjf static void
   1355  1.114.6.2  mjf db_stack_trace_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
   1356  1.114.6.2  mjf {
   1357  1.114.6.2  mjf 	register const char *cp = modif;
   1358  1.114.6.2  mjf 	register char c;
   1359  1.114.6.2  mjf 	void (*pr)(const char *, ...);
   1360  1.114.6.2  mjf 
   1361  1.114.6.2  mjf 	pr = db_printf;
   1362  1.114.6.2  mjf 	while ((c = *cp++) != 0)
   1363  1.114.6.2  mjf 		if (c == 'l')
   1364  1.114.6.2  mjf 			pr = printf;
   1365  1.114.6.2  mjf 
   1366  1.114.6.2  mjf 	if (count == -1)
   1367  1.114.6.2  mjf 		count = 65535;
   1368  1.114.6.2  mjf 
   1369  1.114.6.2  mjf 	db_stack_trace_print(addr, have_addr, count, modif, pr);
   1370  1.114.6.2  mjf }
   1371  1.114.6.2  mjf 
   1372  1.114.6.2  mjf static void
   1373  1.114.6.2  mjf db_sync_cmd(db_expr_t addr, bool have_addr,
   1374  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1375  1.114.6.2  mjf {
   1376  1.114.6.2  mjf 
   1377  1.114.6.2  mjf 	/*
   1378  1.114.6.2  mjf 	 * We are leaving DDB, never to return upward.
   1379  1.114.6.2  mjf 	 * Clear db_recover so that we can debug faults in functions
   1380  1.114.6.2  mjf 	 * called from cpu_reboot.
   1381  1.114.6.2  mjf 	 */
   1382  1.114.6.2  mjf 	db_recover = 0;
   1383  1.114.6.2  mjf 	panicstr = "dump forced via kernel debugger";
   1384  1.114.6.2  mjf 	cpu_reboot(RB_DUMP, NULL);
   1385  1.114.6.2  mjf }
   1386  1.114.6.2  mjf 
   1387  1.114.6.2  mjf /*
   1388  1.114.6.2  mjf  * Describe what an address is
   1389  1.114.6.2  mjf  */
   1390  1.114.6.2  mjf void
   1391  1.114.6.2  mjf db_whatis_cmd(db_expr_t address, bool have_addr,
   1392  1.114.6.2  mjf     db_expr_t count, const char *modif)
   1393  1.114.6.2  mjf {
   1394  1.114.6.2  mjf 	const uintptr_t addr = (uintptr_t)address;
   1395  1.114.6.2  mjf 
   1396  1.114.6.2  mjf 	lwp_whatis(addr, db_printf);
   1397  1.114.6.2  mjf 	pool_whatis(addr, db_printf);
   1398  1.114.6.2  mjf 	vmem_whatis(addr, db_printf);
   1399  1.114.6.2  mjf 	uvm_whatis(addr, db_printf);
   1400  1.114.6.2  mjf }
   1401