db_command.c revision 92756
18876Srgrimes/*
24Srgrimes * Mach Operating System
34Srgrimes * Copyright (c) 1991,1990 Carnegie Mellon University
44Srgrimes * All Rights Reserved.
58876Srgrimes *
64Srgrimes * Permission to use, copy, modify and distribute this software and its
74Srgrimes * documentation is hereby granted, provided that both the copyright
84Srgrimes * notice and this permission notice appear in all copies of the
94Srgrimes * software, derivative works or modified versions, and any portions
104Srgrimes * thereof, and that both notices appear in supporting documentation.
118876Srgrimes *
128876Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
134Srgrimes * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
158876Srgrimes *
164Srgrimes * Carnegie Mellon requests users of this software to return to
178876Srgrimes *
184Srgrimes *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
194Srgrimes *  School of Computer Science
204Srgrimes *  Carnegie Mellon University
214Srgrimes *  Pittsburgh PA 15213-3890
228876Srgrimes *
234Srgrimes * any improvements or extensions that they make and grant Carnegie the
244Srgrimes * rights to redistribute these changes.
254Srgrimes *
2650477Speter * $FreeBSD: head/sys/ddb/db_command.c 92756 2002-03-20 05:14:42Z alfred $
274Srgrimes */
28623Srgrimes
294Srgrimes/*
304Srgrimes *	Author: David B. Golub, Carnegie Mellon University
314Srgrimes *	Date:	7/90
324Srgrimes */
33623Srgrimes
344Srgrimes/*
354Srgrimes * Command dispatcher.
364Srgrimes */
372056Swollman#include <sys/param.h>
3842654Sjdp#include <sys/linker_set.h>
3986998Sdd#include <sys/lock.h>
4086998Sdd#include <sys/mutex.h>
4186998Sdd#include <sys/proc.h>
4217848Spst#include <sys/reboot.h>
4386998Sdd#include <sys/signalvar.h>
442056Swollman#include <sys/systm.h>
4549558Sphk#include <sys/cons.h>
4612734Sbde
472056Swollman#include <ddb/ddb.h>
4812473Sbde#include <ddb/db_command.h>
494Srgrimes#include <ddb/db_lex.h>
504Srgrimes#include <ddb/db_output.h>
514Srgrimes
5286109Sarr#include <machine/md_var.h>
5379418Sjulian#include <machine/setjmp.h>
544Srgrimes
554Srgrimes/*
564Srgrimes * Exported global variables
574Srgrimes */
584Srgrimesboolean_t	db_cmd_loop_done;
5918296Sbdedb_addr_t	db_dot;
604Srgrimesjmp_buf		db_jmpbuf;
614Srgrimesdb_addr_t	db_last_addr;
624Srgrimesdb_addr_t	db_prev;
634Srgrimesdb_addr_t	db_next;
644Srgrimes
6578161SpeterSET_DECLARE(db_cmd_set, struct command);
6678161SpeterSET_DECLARE(db_show_cmd_set, struct command);
6778161Speter
6812515Sphkstatic db_cmdfcn_t	db_fncall;
6917848Spststatic db_cmdfcn_t	db_gdb;
7086998Sddstatic db_cmdfcn_t	db_kill;
7185944Speterstatic db_cmdfcn_t	db_reset;
7217848Spst
7318296Sbde/* XXX this is actually forward-static. */
7418296Sbdeextern struct command	db_show_cmds[];
7518296Sbde
764Srgrimes/*
774Srgrimes * if 'ed' style: 'dot' is set at start of last item printed,
784Srgrimes * and '+' points to next line.
794Srgrimes * Otherwise: 'dot' points to next item, '..' points to last.
804Srgrimes */
8112515Sphkstatic boolean_t	db_ed_style = TRUE;
824Srgrimes
834Srgrimes/*
844Srgrimes * Utility routine - discard tokens through end-of-line.
854Srgrimes */
864Srgrimesvoid
874Srgrimesdb_skip_to_eol()
884Srgrimes{
894Srgrimes	int	t;
904Srgrimes	do {
914Srgrimes	    t = db_read_token();
924Srgrimes	} while (t != tEOL);
934Srgrimes}
944Srgrimes
954Srgrimes/*
964Srgrimes * Results of command search.
974Srgrimes */
984Srgrimes#define	CMD_UNIQUE	0
994Srgrimes#define	CMD_FOUND	1
1004Srgrimes#define	CMD_NONE	2
1014Srgrimes#define	CMD_AMBIGUOUS	3
1024Srgrimes#define	CMD_HELP	4
1034Srgrimes
10492756Salfredstatic void	db_cmd_list(struct command *table,
10578161Speter				 struct command **aux_tablep,
10692756Salfred				 struct command **aux_tablep_end);
10792756Salfredstatic int	db_cmd_search(char *name, struct command *table,
10818296Sbde				   struct command **aux_tablep,
10978161Speter				   struct command **aux_tablep_end,
11092756Salfred				   struct command **cmdp);
11192756Salfredstatic void	db_command(struct command **last_cmdp,
11218296Sbde				struct command *cmd_table,
11378161Speter				struct command **aux_cmd_tablep,
11492756Salfred				struct command **aux_cmd_tablep_end);
11512473Sbde
1164Srgrimes/*
1174Srgrimes * Search for command prefix.
1184Srgrimes */
11912515Sphkstatic int
12078161Speterdb_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp)
1214Srgrimes	char *		name;
1224Srgrimes	struct command	*table;
12318296Sbde	struct command	**aux_tablep;
12478161Speter	struct command	**aux_tablep_end;
1254Srgrimes	struct command	**cmdp;	/* out */
1264Srgrimes{
1274Srgrimes	struct command	*cmd;
12818296Sbde	struct command	**aux_cmdp;
1294Srgrimes	int		result = CMD_NONE;
1304Srgrimes
1314Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
1324Srgrimes	    register char *lp;
1334Srgrimes	    register char *rp;
1344Srgrimes	    register int  c;
1354Srgrimes
1364Srgrimes	    lp = name;
1374Srgrimes	    rp = cmd->name;
1384Srgrimes	    while ((c = *lp) == *rp) {
1394Srgrimes		if (c == 0) {
1404Srgrimes		    /* complete match */
1414Srgrimes		    *cmdp = cmd;
1424Srgrimes		    return (CMD_UNIQUE);
1434Srgrimes		}
1444Srgrimes		lp++;
1454Srgrimes		rp++;
1464Srgrimes	    }
1474Srgrimes	    if (c == 0) {
1484Srgrimes		/* end of name, not end of command -
1494Srgrimes		   partial match */
1504Srgrimes		if (result == CMD_FOUND) {
1514Srgrimes		    result = CMD_AMBIGUOUS;
1524Srgrimes		    /* but keep looking for a full match -
1534Srgrimes		       this lets us match single letters */
1544Srgrimes		}
1554Srgrimes		else {
1564Srgrimes		    *cmdp = cmd;
1574Srgrimes		    result = CMD_FOUND;
1584Srgrimes		}
1594Srgrimes	    }
1604Srgrimes	}
16118296Sbde	if (result == CMD_NONE && aux_tablep != 0)
16218296Sbde	    /* XXX repeat too much code. */
16378161Speter	    for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
16418296Sbde		register char *lp;
16518296Sbde		register char *rp;
16618296Sbde		register int  c;
16718296Sbde
16818296Sbde		lp = name;
16918296Sbde		rp = (*aux_cmdp)->name;
17018296Sbde		while ((c = *lp) == *rp) {
17118296Sbde		    if (c == 0) {
17218296Sbde			/* complete match */
17318296Sbde			*cmdp = *aux_cmdp;
17418296Sbde			return (CMD_UNIQUE);
17518296Sbde		    }
17618296Sbde		    lp++;
17718296Sbde		    rp++;
17818296Sbde		}
17918296Sbde		if (c == 0) {
18018296Sbde		    /* end of name, not end of command -
18118296Sbde		       partial match */
18218296Sbde		    if (result == CMD_FOUND) {
18318296Sbde			result = CMD_AMBIGUOUS;
18418296Sbde			/* but keep looking for a full match -
18518296Sbde			   this lets us match single letters */
18618296Sbde		    }
18718296Sbde		    else {
18818296Sbde			*cmdp = *aux_cmdp;
18918296Sbde			result = CMD_FOUND;
19018296Sbde		    }
19118296Sbde		}
19218296Sbde	    }
1934Srgrimes	if (result == CMD_NONE) {
1944Srgrimes	    /* check for 'help' */
1954Srgrimes		if (name[0] == 'h' && name[1] == 'e'
1964Srgrimes		    && name[2] == 'l' && name[3] == 'p')
1974Srgrimes			result = CMD_HELP;
1984Srgrimes	}
1994Srgrimes	return (result);
2004Srgrimes}
2014Srgrimes
20212515Sphkstatic void
20378161Speterdb_cmd_list(table, aux_tablep, aux_tablep_end)
2044Srgrimes	struct command *table;
20518296Sbde	struct command **aux_tablep;
20678161Speter	struct command **aux_tablep_end;
2074Srgrimes{
2084Srgrimes	register struct command *cmd;
20918296Sbde	register struct command **aux_cmdp;
2104Srgrimes
2114Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
2124Srgrimes	    db_printf("%-12s", cmd->name);
2134Srgrimes	    db_end_line();
2144Srgrimes	}
21518296Sbde	if (aux_tablep == 0)
21618296Sbde	    return;
21778161Speter	for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
21818296Sbde	    db_printf("%-12s", (*aux_cmdp)->name);
21918296Sbde	    db_end_line();
22018296Sbde	}
2214Srgrimes}
2224Srgrimes
22312515Sphkstatic void
22478161Speterdb_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end)
2254Srgrimes	struct command	**last_cmdp;	/* IN_OUT */
2264Srgrimes	struct command	*cmd_table;
22718296Sbde	struct command	**aux_cmd_tablep;
22878161Speter	struct command	**aux_cmd_tablep_end;
2294Srgrimes{
2304Srgrimes	struct command	*cmd;
2314Srgrimes	int		t;
2324Srgrimes	char		modif[TOK_STRING_SIZE];
2334Srgrimes	db_expr_t	addr, count;
234798Swollman	boolean_t	have_addr = FALSE;
2354Srgrimes	int		result;
2364Srgrimes
2374Srgrimes	t = db_read_token();
2384Srgrimes	if (t == tEOL) {
2394Srgrimes	    /* empty line repeats last command, at 'next' */
2404Srgrimes	    cmd = *last_cmdp;
2414Srgrimes	    addr = (db_expr_t)db_next;
2424Srgrimes	    have_addr = FALSE;
2434Srgrimes	    count = 1;
2444Srgrimes	    modif[0] = '\0';
2454Srgrimes	}
2464Srgrimes	else if (t == tEXCL) {
24710348Sbde	    db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0);
2484Srgrimes	    return;
2494Srgrimes	}
2504Srgrimes	else if (t != tIDENT) {
2514Srgrimes	    db_printf("?\n");
2524Srgrimes	    db_flush_lex();
2534Srgrimes	    return;
2544Srgrimes	}
2554Srgrimes	else {
2564Srgrimes	    /*
2574Srgrimes	     * Search for command
2584Srgrimes	     */
2594Srgrimes	    while (cmd_table) {
2604Srgrimes		result = db_cmd_search(db_tok_string,
2614Srgrimes				       cmd_table,
26218296Sbde				       aux_cmd_tablep,
26378161Speter				       aux_cmd_tablep_end,
2644Srgrimes				       &cmd);
2654Srgrimes		switch (result) {
2664Srgrimes		    case CMD_NONE:
2674Srgrimes			db_printf("No such command\n");
2684Srgrimes			db_flush_lex();
2694Srgrimes			return;
2704Srgrimes		    case CMD_AMBIGUOUS:
2714Srgrimes			db_printf("Ambiguous\n");
2724Srgrimes			db_flush_lex();
2734Srgrimes			return;
2744Srgrimes		    case CMD_HELP:
27578161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2764Srgrimes			db_flush_lex();
2774Srgrimes			return;
2784Srgrimes		    default:
2794Srgrimes			break;
2804Srgrimes		}
2814Srgrimes		if ((cmd_table = cmd->more) != 0) {
28218296Sbde		    /* XXX usually no more aux's. */
28318296Sbde		    aux_cmd_tablep = 0;
28418296Sbde		    if (cmd_table == db_show_cmds)
28578161Speter			aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
28678161Speter			aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
28718296Sbde
2884Srgrimes		    t = db_read_token();
2894Srgrimes		    if (t != tIDENT) {
29078161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2914Srgrimes			db_flush_lex();
2924Srgrimes			return;
2934Srgrimes		    }
2944Srgrimes		}
2954Srgrimes	    }
2964Srgrimes
2974Srgrimes	    if ((cmd->flag & CS_OWN) == 0) {
2984Srgrimes		/*
2994Srgrimes		 * Standard syntax:
3004Srgrimes		 * command [/modifier] [addr] [,count]
3014Srgrimes		 */
3024Srgrimes		t = db_read_token();
3034Srgrimes		if (t == tSLASH) {
3044Srgrimes		    t = db_read_token();
3054Srgrimes		    if (t != tIDENT) {
3064Srgrimes			db_printf("Bad modifier\n");
3074Srgrimes			db_flush_lex();
3084Srgrimes			return;
3094Srgrimes		    }
3104Srgrimes		    db_strcpy(modif, db_tok_string);
3114Srgrimes		}
3124Srgrimes		else {
3134Srgrimes		    db_unread_token(t);
3144Srgrimes		    modif[0] = '\0';
3154Srgrimes		}
3164Srgrimes
3174Srgrimes		if (db_expression(&addr)) {
3184Srgrimes		    db_dot = (db_addr_t) addr;
3194Srgrimes		    db_last_addr = db_dot;
3204Srgrimes		    have_addr = TRUE;
3214Srgrimes		}
3224Srgrimes		else {
3234Srgrimes		    addr = (db_expr_t) db_dot;
3244Srgrimes		    have_addr = FALSE;
3254Srgrimes		}
3264Srgrimes		t = db_read_token();
3274Srgrimes		if (t == tCOMMA) {
3284Srgrimes		    if (!db_expression(&count)) {
3294Srgrimes			db_printf("Count missing\n");
3304Srgrimes			db_flush_lex();
3314Srgrimes			return;
3324Srgrimes		    }
3334Srgrimes		}
3344Srgrimes		else {
3354Srgrimes		    db_unread_token(t);
3364Srgrimes		    count = -1;
3374Srgrimes		}
3384Srgrimes		if ((cmd->flag & CS_MORE) == 0) {
3394Srgrimes		    db_skip_to_eol();
3404Srgrimes		}
3414Srgrimes	    }
3424Srgrimes	}
3434Srgrimes	*last_cmdp = cmd;
3444Srgrimes	if (cmd != 0) {
3454Srgrimes	    /*
3464Srgrimes	     * Execute the command.
3474Srgrimes	     */
3484Srgrimes	    (*cmd->fcn)(addr, have_addr, count, modif);
3494Srgrimes
3504Srgrimes	    if (cmd->flag & CS_SET_DOT) {
3514Srgrimes		/*
3524Srgrimes		 * If command changes dot, set dot to
3534Srgrimes		 * previous address displayed (if 'ed' style).
3544Srgrimes		 */
3554Srgrimes		if (db_ed_style) {
3564Srgrimes		    db_dot = db_prev;
3574Srgrimes		}
3584Srgrimes		else {
3594Srgrimes		    db_dot = db_next;
3604Srgrimes		}
3614Srgrimes	    }
3624Srgrimes	    else {
3634Srgrimes		/*
3644Srgrimes		 * If command does not change dot,
3654Srgrimes		 * set 'next' location to be the same.
3664Srgrimes		 */
3674Srgrimes		db_next = db_dot;
3684Srgrimes	    }
3694Srgrimes	}
3704Srgrimes}
3714Srgrimes
3724Srgrimes/*
3734Srgrimes * 'show' commands
3744Srgrimes */
3752112Swollman
37612515Sphkstatic struct command db_show_all_cmds[] = {
3774Srgrimes#if 0
3781147Sguido	{ "threads",	db_show_all_threads,	0,	0 },
3792320Sdg#endif
3801549Srgrimes	{ "procs",	db_ps,			0,	0 },
3814Srgrimes	{ (char *)0 }
3824Srgrimes};
3834Srgrimes
38412515Sphkstatic struct command db_show_cmds[] = {
3854Srgrimes	{ "all",	0,			0,	db_show_all_cmds },
3864Srgrimes	{ "registers",	db_show_regs,		0,	0 },
3874Srgrimes	{ "breaks",	db_listbreak_cmd, 	0,	0 },
3884Srgrimes#if 0
3894Srgrimes	{ "thread",	db_show_one_thread,	0,	0 },
3904Srgrimes#endif
3914Srgrimes#if 0
3924Srgrimes	{ "port",	ipc_port_print,		0,	0 },
3934Srgrimes#endif
3944Srgrimes	{ (char *)0, }
3954Srgrimes};
3964Srgrimes
39712515Sphkstatic struct command db_command_table[] = {
3984Srgrimes	{ "print",	db_print_cmd,		0,	0 },
3996920Sjoerg	{ "p",		db_print_cmd,		0,	0 },
4004Srgrimes	{ "examine",	db_examine_cmd,		CS_SET_DOT, 0 },
4014Srgrimes	{ "x",		db_examine_cmd,		CS_SET_DOT, 0 },
4024Srgrimes	{ "search",	db_search_cmd,		CS_OWN|CS_SET_DOT, 0 },
4034Srgrimes	{ "set",	db_set_cmd,		CS_OWN,	0 },
4044Srgrimes	{ "write",	db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
4054Srgrimes	{ "w",		db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
4064Srgrimes	{ "delete",	db_delete_cmd,		0,	0 },
4074Srgrimes	{ "d",		db_delete_cmd,		0,	0 },
4084Srgrimes	{ "break",	db_breakpoint_cmd,	0,	0 },
4094Srgrimes	{ "dwatch",	db_deletewatch_cmd,	0,	0 },
4104Srgrimes	{ "watch",	db_watchpoint_cmd,	CS_MORE,0 },
41179573Sbsd	{ "dhwatch",	db_deletehwatch_cmd,	0,      0 },
41279573Sbsd	{ "hwatch",	db_hwatchpoint_cmd,	0,      0 },
4134Srgrimes	{ "step",	db_single_step_cmd,	0,	0 },
4144Srgrimes	{ "s",		db_single_step_cmd,	0,	0 },
4154Srgrimes	{ "continue",	db_continue_cmd,	0,	0 },
4164Srgrimes	{ "c",		db_continue_cmd,	0,	0 },
4174Srgrimes	{ "until",	db_trace_until_call_cmd,0,	0 },
4184Srgrimes	{ "next",	db_trace_until_matching_cmd,0,	0 },
4194Srgrimes	{ "match",	db_trace_until_matching_cmd,0,	0 },
4204Srgrimes	{ "trace",	db_stack_trace_cmd,	0,	0 },
4214Srgrimes	{ "call",	db_fncall,		CS_OWN,	0 },
4224Srgrimes	{ "show",	0,			0,	db_show_cmds },
4231147Sguido	{ "ps",		db_ps,			0,	0 },
42417848Spst	{ "gdb",	db_gdb,			0,	0 },
42585944Speter	{ "reset",	db_reset,		0,	0 },
42686998Sdd	{ "kill",	db_kill,		CS_OWN,	0 },
4274Srgrimes	{ (char *)0, }
4284Srgrimes};
4294Srgrimes
43012515Sphkstatic struct command	*db_last_command = 0;
4314Srgrimes
4327090Sbde#if 0
4334Srgrimesvoid
4344Srgrimesdb_help_cmd()
4354Srgrimes{
4364Srgrimes	struct command *cmd = db_command_table;
4374Srgrimes
4384Srgrimes	while (cmd->name != 0) {
4394Srgrimes	    db_printf("%-12s", cmd->name);
4404Srgrimes	    db_end_line();
4414Srgrimes	    cmd++;
4424Srgrimes	}
4434Srgrimes}
4447090Sbde#endif
4454Srgrimes
44633296Sbde/*
44733296Sbde * At least one non-optional command must be implemented using
44833296Sbde * DB_COMMAND() so that db_cmd_set gets created.  Here is one.
44933296Sbde */
45033296SbdeDB_COMMAND(panic, db_panic)
4516204Sphk{
4527170Sdg	panic("from debugger");
4536204Sphk}
4546204Sphk
4556204Sphkvoid
4564Srgrimesdb_command_loop()
4574Srgrimes{
4584Srgrimes	/*
4594Srgrimes	 * Initialize 'prev' and 'next' to dot.
4604Srgrimes	 */
4614Srgrimes	db_prev = db_dot;
4624Srgrimes	db_next = db_dot;
4634Srgrimes
4644Srgrimes	db_cmd_loop_done = 0;
4654Srgrimes	while (!db_cmd_loop_done) {
4664Srgrimes
4674Srgrimes	    (void) setjmp(db_jmpbuf);
4684Srgrimes	    if (db_print_position() != 0)
4694Srgrimes		db_printf("\n");
4704Srgrimes
4714Srgrimes	    db_printf("db> ");
4724Srgrimes	    (void) db_read_line();
4734Srgrimes
47418296Sbde	    db_command(&db_last_command, db_command_table,
47578161Speter		       SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
4764Srgrimes	}
4774Srgrimes}
4784Srgrimes
4794Srgrimesvoid
4804Srgrimesdb_error(s)
4814Srgrimes	char *s;
4824Srgrimes{
4834Srgrimes	if (s)
48479884Skris	    db_printf("%s", s);
4854Srgrimes	db_flush_lex();
4864Srgrimes	longjmp(db_jmpbuf, 1);
4874Srgrimes}
4884Srgrimes
4894Srgrimes
4904Srgrimes/*
4914Srgrimes * Call random function:
4924Srgrimes * !expr(arg,arg,arg)
4934Srgrimes */
49412515Sphkstatic void
49510348Sbdedb_fncall(dummy1, dummy2, dummy3, dummy4)
49610348Sbde	db_expr_t	dummy1;
49710348Sbde	boolean_t	dummy2;
49810348Sbde	db_expr_t	dummy3;
49910348Sbde	char *		dummy4;
5004Srgrimes{
5014Srgrimes	db_expr_t	fn_addr;
50212473Sbde#define	MAXARGS		11	/* XXX only 10 are passed */
5034Srgrimes	db_expr_t	args[MAXARGS];
5044Srgrimes	int		nargs = 0;
5054Srgrimes	db_expr_t	retval;
50692756Salfred	typedef db_expr_t fcn_10args_t(db_expr_t, db_expr_t, db_expr_t,
50712473Sbde					    db_expr_t, db_expr_t, db_expr_t,
50812473Sbde					    db_expr_t, db_expr_t, db_expr_t,
50992756Salfred					    db_expr_t);
51012473Sbde	fcn_10args_t	*func;
5114Srgrimes	int		t;
5124Srgrimes
5134Srgrimes	if (!db_expression(&fn_addr)) {
5144Srgrimes	    db_printf("Bad function\n");
5154Srgrimes	    db_flush_lex();
5164Srgrimes	    return;
5174Srgrimes	}
51812473Sbde	func = (fcn_10args_t *)fn_addr;	/* XXX */
5194Srgrimes
5204Srgrimes	t = db_read_token();
5214Srgrimes	if (t == tLPAREN) {
5224Srgrimes	    if (db_expression(&args[0])) {
5234Srgrimes		nargs++;
5244Srgrimes		while ((t = db_read_token()) == tCOMMA) {
5254Srgrimes		    if (nargs == MAXARGS) {
5264Srgrimes			db_printf("Too many arguments\n");
5274Srgrimes			db_flush_lex();
5284Srgrimes			return;
5294Srgrimes		    }
5304Srgrimes		    if (!db_expression(&args[nargs])) {
5314Srgrimes			db_printf("Argument missing\n");
5324Srgrimes			db_flush_lex();
5334Srgrimes			return;
5344Srgrimes		    }
5354Srgrimes		    nargs++;
5364Srgrimes		}
5374Srgrimes		db_unread_token(t);
5384Srgrimes	    }
5394Srgrimes	    if (db_read_token() != tRPAREN) {
5404Srgrimes		db_printf("?\n");
5414Srgrimes		db_flush_lex();
5424Srgrimes		return;
5434Srgrimes	    }
5444Srgrimes	}
5454Srgrimes	db_skip_to_eol();
5464Srgrimes
5474Srgrimes	while (nargs < MAXARGS) {
5484Srgrimes	    args[nargs++] = 0;
5494Srgrimes	}
5504Srgrimes
5514Srgrimes	retval = (*func)(args[0], args[1], args[2], args[3], args[4],
5524Srgrimes			 args[5], args[6], args[7], args[8], args[9] );
55348407Speter	db_printf("%#lr\n", (long)retval);
5544Srgrimes}
55517848Spst
55617848Spst/* Enter GDB remote protocol debugger on the next trap. */
55717848Spst
55846783Sphkdev_t	   gdbdev = NODEV;
55946783Sphkcn_getc_t *gdb_getc;
56046783Sphkcn_putc_t *gdb_putc;
56146658Smckusick
56217848Spststatic void
56317848Spstdb_gdb (dummy1, dummy2, dummy3, dummy4)
56417848Spst	db_expr_t	dummy1;
56517848Spst	boolean_t	dummy2;
56617848Spst	db_expr_t	dummy3;
56717848Spst	char *		dummy4;
56817848Spst{
56946658Smckusick
57046783Sphk	if (gdbdev == NODEV) {
57146658Smckusick		db_printf("No gdb port enabled. Set flag 0x80 on desired port\n");
57246658Smckusick		db_printf("in your configuration file (currently sio only).\n");
57346658Smckusick		return;
57446658Smckusick	}
57517848Spst	boothowto ^= RB_GDB;
57617848Spst
57717848Spst	db_printf("Next trap will enter %s\n",
57817848Spst		   boothowto & RB_GDB ? "GDB remote protocol mode"
57917848Spst				      : "DDB debugger");
58017848Spst}
58185944Speter
58285944Speterstatic void
58386998Sdddb_kill(dummy1, dummy2, dummy3, dummy4)
58486998Sdd	db_expr_t	dummy1;
58586998Sdd	boolean_t	dummy2;
58686998Sdd	db_expr_t	dummy3;
58786998Sdd	char *		dummy4;
58886998Sdd{
58986998Sdd	db_expr_t old_radix, pid, sig;
59086998Sdd	struct proc *p;
59186998Sdd
59286998Sdd#define DB_ERROR(f)	do { db_printf f; db_flush_lex(); goto out; } while (0)
59386998Sdd
59486998Sdd	/*
59586998Sdd	 * PIDs and signal numbers are typically represented in base
59686998Sdd	 * 10, so make that the default here.  It can, of course, be
59786998Sdd	 * overridden by specifying a prefix.
59886998Sdd	 */
59986998Sdd	old_radix = db_radix;
60086998Sdd	db_radix = 10;
60186998Sdd	/* Retrieve arguments. */
60286998Sdd	if (!db_expression(&sig))
60386998Sdd		DB_ERROR(("Missing signal number\n"));
60486998Sdd	if (!db_expression(&pid))
60586998Sdd		DB_ERROR(("Missing process ID\n"));
60686998Sdd	db_skip_to_eol();
60786998Sdd	if (sig < 0 || sig > _SIG_MAXSIG)
60886998Sdd		DB_ERROR(("Signal number out of range\n"));
60986998Sdd
61086998Sdd	/*
61186998Sdd	 * Find the process in question.  allproc_lock is not needed
61286998Sdd	 * since we're in DDB.
61386998Sdd	 */
61486998Sdd	/* sx_slock(&allproc_lock); */
61586998Sdd	LIST_FOREACH(p, &allproc, p_list)
61686998Sdd	    if (p->p_pid == pid)
61786998Sdd		    break;
61886998Sdd	/* sx_sunlock(&allproc_lock); */
61986998Sdd	if (p == NULL)
62089442Smjacob		DB_ERROR(("Can't find process with pid %ld\n", (long) pid));
62186998Sdd
62286998Sdd	/* If it's already locked, bail; otherwise, do the deed. */
62386998Sdd	if (PROC_TRYLOCK(p) == 0)
62489442Smjacob		DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
62586998Sdd	else {
62686998Sdd		psignal(p, sig);
62786998Sdd		PROC_UNLOCK(p);
62886998Sdd	}
62986998Sdd
63086998Sddout:
63186998Sdd	db_radix = old_radix;
63286998Sdd#undef DB_ERROR
63386998Sdd}
63486998Sdd
63586998Sddstatic void
63685944Speterdb_reset(dummy1, dummy2, dummy3, dummy4)
63785944Speter	db_expr_t	dummy1;
63885944Speter	boolean_t	dummy2;
63985944Speter	db_expr_t	dummy3;
64085944Speter	char *		dummy4;
64185944Speter{
64285944Speter
64385944Speter	cpu_reset();
64485944Speter}
645