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