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