db_command.c revision 118990
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 */
264Srgrimes/*
274Srgrimes *	Author: David B. Golub, Carnegie Mellon University
284Srgrimes *	Date:	7/90
294Srgrimes */
304Srgrimes/*
314Srgrimes * Command dispatcher.
324Srgrimes */
33116176Sobrien
34116176Sobrien#include <sys/cdefs.h>
35116176Sobrien__FBSDID("$FreeBSD: head/sys/ddb/db_command.c 118990 2003-08-16 16:57:57Z marcel $");
36116176Sobrien
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
52118990Smarcel#include <machine/cpu.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
10493009Sbdestatic void	db_cmd_list(struct command *table, struct command **aux_tablep,
10593009Sbde		    struct command **aux_tablep_end);
10692756Salfredstatic int	db_cmd_search(char *name, struct command *table,
10793009Sbde		    struct command **aux_tablep,
10893009Sbde		    struct command **aux_tablep_end, struct command **cmdp);
10992756Salfredstatic void	db_command(struct command **last_cmdp,
11093009Sbde		    struct command *cmd_table, struct command **aux_cmd_tablep,
11193009Sbde		    struct command **aux_cmd_tablep_end);
11212473Sbde
1134Srgrimes/*
1144Srgrimes * Search for command prefix.
1154Srgrimes */
11612515Sphkstatic int
11778161Speterdb_cmd_search(name, table, aux_tablep, aux_tablep_end, cmdp)
1184Srgrimes	char *		name;
1194Srgrimes	struct command	*table;
12018296Sbde	struct command	**aux_tablep;
12178161Speter	struct command	**aux_tablep_end;
1224Srgrimes	struct command	**cmdp;	/* out */
1234Srgrimes{
1244Srgrimes	struct command	*cmd;
12518296Sbde	struct command	**aux_cmdp;
1264Srgrimes	int		result = CMD_NONE;
1274Srgrimes
1284Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
1294Srgrimes	    register char *lp;
1304Srgrimes	    register char *rp;
1314Srgrimes	    register int  c;
1324Srgrimes
1334Srgrimes	    lp = name;
1344Srgrimes	    rp = cmd->name;
1354Srgrimes	    while ((c = *lp) == *rp) {
1364Srgrimes		if (c == 0) {
1374Srgrimes		    /* complete match */
1384Srgrimes		    *cmdp = cmd;
1394Srgrimes		    return (CMD_UNIQUE);
1404Srgrimes		}
1414Srgrimes		lp++;
1424Srgrimes		rp++;
1434Srgrimes	    }
1444Srgrimes	    if (c == 0) {
1454Srgrimes		/* end of name, not end of command -
1464Srgrimes		   partial match */
1474Srgrimes		if (result == CMD_FOUND) {
1484Srgrimes		    result = CMD_AMBIGUOUS;
1494Srgrimes		    /* but keep looking for a full match -
1504Srgrimes		       this lets us match single letters */
1514Srgrimes		}
1524Srgrimes		else {
1534Srgrimes		    *cmdp = cmd;
1544Srgrimes		    result = CMD_FOUND;
1554Srgrimes		}
1564Srgrimes	    }
1574Srgrimes	}
15818296Sbde	if (result == CMD_NONE && aux_tablep != 0)
15918296Sbde	    /* XXX repeat too much code. */
16078161Speter	    for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
16118296Sbde		register char *lp;
16218296Sbde		register char *rp;
16318296Sbde		register int  c;
16418296Sbde
16518296Sbde		lp = name;
16618296Sbde		rp = (*aux_cmdp)->name;
16718296Sbde		while ((c = *lp) == *rp) {
16818296Sbde		    if (c == 0) {
16918296Sbde			/* complete match */
17018296Sbde			*cmdp = *aux_cmdp;
17118296Sbde			return (CMD_UNIQUE);
17218296Sbde		    }
17318296Sbde		    lp++;
17418296Sbde		    rp++;
17518296Sbde		}
17618296Sbde		if (c == 0) {
17718296Sbde		    /* end of name, not end of command -
17818296Sbde		       partial match */
17918296Sbde		    if (result == CMD_FOUND) {
18018296Sbde			result = CMD_AMBIGUOUS;
18118296Sbde			/* but keep looking for a full match -
18218296Sbde			   this lets us match single letters */
18318296Sbde		    }
18418296Sbde		    else {
18518296Sbde			*cmdp = *aux_cmdp;
18618296Sbde			result = CMD_FOUND;
18718296Sbde		    }
18818296Sbde		}
18918296Sbde	    }
1904Srgrimes	if (result == CMD_NONE) {
1914Srgrimes	    /* check for 'help' */
1924Srgrimes		if (name[0] == 'h' && name[1] == 'e'
1934Srgrimes		    && name[2] == 'l' && name[3] == 'p')
1944Srgrimes			result = CMD_HELP;
1954Srgrimes	}
1964Srgrimes	return (result);
1974Srgrimes}
1984Srgrimes
19912515Sphkstatic void
20078161Speterdb_cmd_list(table, aux_tablep, aux_tablep_end)
2014Srgrimes	struct command *table;
20218296Sbde	struct command **aux_tablep;
20378161Speter	struct command **aux_tablep_end;
2044Srgrimes{
2054Srgrimes	register struct command *cmd;
20618296Sbde	register struct command **aux_cmdp;
2074Srgrimes
2084Srgrimes	for (cmd = table; cmd->name != 0; cmd++) {
2094Srgrimes	    db_printf("%-12s", cmd->name);
2104Srgrimes	    db_end_line();
2114Srgrimes	}
21218296Sbde	if (aux_tablep == 0)
21318296Sbde	    return;
21478161Speter	for (aux_cmdp = aux_tablep; aux_cmdp < aux_tablep_end; aux_cmdp++) {
21518296Sbde	    db_printf("%-12s", (*aux_cmdp)->name);
21618296Sbde	    db_end_line();
21718296Sbde	}
2184Srgrimes}
2194Srgrimes
22012515Sphkstatic void
22178161Speterdb_command(last_cmdp, cmd_table, aux_cmd_tablep, aux_cmd_tablep_end)
2224Srgrimes	struct command	**last_cmdp;	/* IN_OUT */
2234Srgrimes	struct command	*cmd_table;
22418296Sbde	struct command	**aux_cmd_tablep;
22578161Speter	struct command	**aux_cmd_tablep_end;
2264Srgrimes{
2274Srgrimes	struct command	*cmd;
2284Srgrimes	int		t;
2294Srgrimes	char		modif[TOK_STRING_SIZE];
2304Srgrimes	db_expr_t	addr, count;
231798Swollman	boolean_t	have_addr = FALSE;
2324Srgrimes	int		result;
2334Srgrimes
2344Srgrimes	t = db_read_token();
2354Srgrimes	if (t == tEOL) {
2364Srgrimes	    /* empty line repeats last command, at 'next' */
2374Srgrimes	    cmd = *last_cmdp;
2384Srgrimes	    addr = (db_expr_t)db_next;
2394Srgrimes	    have_addr = FALSE;
2404Srgrimes	    count = 1;
2414Srgrimes	    modif[0] = '\0';
2424Srgrimes	}
2434Srgrimes	else if (t == tEXCL) {
24410348Sbde	    db_fncall((db_expr_t)0, (boolean_t)0, (db_expr_t)0, (char *)0);
2454Srgrimes	    return;
2464Srgrimes	}
2474Srgrimes	else if (t != tIDENT) {
2484Srgrimes	    db_printf("?\n");
2494Srgrimes	    db_flush_lex();
2504Srgrimes	    return;
2514Srgrimes	}
2524Srgrimes	else {
2534Srgrimes	    /*
2544Srgrimes	     * Search for command
2554Srgrimes	     */
2564Srgrimes	    while (cmd_table) {
2574Srgrimes		result = db_cmd_search(db_tok_string,
2584Srgrimes				       cmd_table,
25918296Sbde				       aux_cmd_tablep,
26078161Speter				       aux_cmd_tablep_end,
2614Srgrimes				       &cmd);
2624Srgrimes		switch (result) {
2634Srgrimes		    case CMD_NONE:
2644Srgrimes			db_printf("No such command\n");
2654Srgrimes			db_flush_lex();
2664Srgrimes			return;
2674Srgrimes		    case CMD_AMBIGUOUS:
2684Srgrimes			db_printf("Ambiguous\n");
2694Srgrimes			db_flush_lex();
2704Srgrimes			return;
2714Srgrimes		    case CMD_HELP:
27278161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2734Srgrimes			db_flush_lex();
2744Srgrimes			return;
2754Srgrimes		    default:
2764Srgrimes			break;
2774Srgrimes		}
2784Srgrimes		if ((cmd_table = cmd->more) != 0) {
27918296Sbde		    /* XXX usually no more aux's. */
28018296Sbde		    aux_cmd_tablep = 0;
281104321Sphk		    if (cmd_table == db_show_cmds) {
28278161Speter			aux_cmd_tablep = SET_BEGIN(db_show_cmd_set);
28378161Speter			aux_cmd_tablep_end = SET_LIMIT(db_show_cmd_set);
284104321Sphk		    }
28518296Sbde
2864Srgrimes		    t = db_read_token();
2874Srgrimes		    if (t != tIDENT) {
28878161Speter			db_cmd_list(cmd_table, aux_cmd_tablep, aux_cmd_tablep_end);
2894Srgrimes			db_flush_lex();
2904Srgrimes			return;
2914Srgrimes		    }
2924Srgrimes		}
2934Srgrimes	    }
2944Srgrimes
2954Srgrimes	    if ((cmd->flag & CS_OWN) == 0) {
2964Srgrimes		/*
2974Srgrimes		 * Standard syntax:
2984Srgrimes		 * command [/modifier] [addr] [,count]
2994Srgrimes		 */
3004Srgrimes		t = db_read_token();
3014Srgrimes		if (t == tSLASH) {
3024Srgrimes		    t = db_read_token();
3034Srgrimes		    if (t != tIDENT) {
3044Srgrimes			db_printf("Bad modifier\n");
3054Srgrimes			db_flush_lex();
3064Srgrimes			return;
3074Srgrimes		    }
3084Srgrimes		    db_strcpy(modif, db_tok_string);
3094Srgrimes		}
3104Srgrimes		else {
3114Srgrimes		    db_unread_token(t);
3124Srgrimes		    modif[0] = '\0';
3134Srgrimes		}
3144Srgrimes
3154Srgrimes		if (db_expression(&addr)) {
3164Srgrimes		    db_dot = (db_addr_t) addr;
3174Srgrimes		    db_last_addr = db_dot;
3184Srgrimes		    have_addr = TRUE;
3194Srgrimes		}
3204Srgrimes		else {
3214Srgrimes		    addr = (db_expr_t) db_dot;
3224Srgrimes		    have_addr = FALSE;
3234Srgrimes		}
3244Srgrimes		t = db_read_token();
3254Srgrimes		if (t == tCOMMA) {
3264Srgrimes		    if (!db_expression(&count)) {
3274Srgrimes			db_printf("Count missing\n");
3284Srgrimes			db_flush_lex();
3294Srgrimes			return;
3304Srgrimes		    }
3314Srgrimes		}
3324Srgrimes		else {
3334Srgrimes		    db_unread_token(t);
3344Srgrimes		    count = -1;
3354Srgrimes		}
3364Srgrimes		if ((cmd->flag & CS_MORE) == 0) {
3374Srgrimes		    db_skip_to_eol();
3384Srgrimes		}
3394Srgrimes	    }
3404Srgrimes	}
3414Srgrimes	*last_cmdp = cmd;
3424Srgrimes	if (cmd != 0) {
3434Srgrimes	    /*
3444Srgrimes	     * Execute the command.
3454Srgrimes	     */
3464Srgrimes	    (*cmd->fcn)(addr, have_addr, count, modif);
347118268Sjhb	    db_setup_paging(NULL, NULL, -1);
3484Srgrimes
3494Srgrimes	    if (cmd->flag & CS_SET_DOT) {
3504Srgrimes		/*
3514Srgrimes		 * If command changes dot, set dot to
3524Srgrimes		 * previous address displayed (if 'ed' style).
3534Srgrimes		 */
3544Srgrimes		if (db_ed_style) {
3554Srgrimes		    db_dot = db_prev;
3564Srgrimes		}
3574Srgrimes		else {
3584Srgrimes		    db_dot = db_next;
3594Srgrimes		}
3604Srgrimes	    }
3614Srgrimes	    else {
3624Srgrimes		/*
3634Srgrimes		 * If command does not change dot,
3644Srgrimes		 * set 'next' location to be the same.
3654Srgrimes		 */
3664Srgrimes		db_next = db_dot;
3674Srgrimes	    }
3684Srgrimes	}
3694Srgrimes}
3704Srgrimes
3714Srgrimes/*
3724Srgrimes * 'show' commands
3734Srgrimes */
3742112Swollman
37512515Sphkstatic struct command db_show_all_cmds[] = {
3764Srgrimes#if 0
3771147Sguido	{ "threads",	db_show_all_threads,	0,	0 },
3782320Sdg#endif
3791549Srgrimes	{ "procs",	db_ps,			0,	0 },
3804Srgrimes	{ (char *)0 }
3814Srgrimes};
3824Srgrimes
38312515Sphkstatic struct command db_show_cmds[] = {
3844Srgrimes	{ "all",	0,			0,	db_show_all_cmds },
3854Srgrimes	{ "registers",	db_show_regs,		0,	0 },
3864Srgrimes	{ "breaks",	db_listbreak_cmd, 	0,	0 },
3874Srgrimes	{ "thread",	db_show_one_thread,	0,	0 },
3884Srgrimes#if 0
3894Srgrimes	{ "port",	ipc_port_print,		0,	0 },
3904Srgrimes#endif
3914Srgrimes	{ (char *)0, }
3924Srgrimes};
3934Srgrimes
39412515Sphkstatic struct command db_command_table[] = {
3954Srgrimes	{ "print",	db_print_cmd,		0,	0 },
3966920Sjoerg	{ "p",		db_print_cmd,		0,	0 },
3974Srgrimes	{ "examine",	db_examine_cmd,		CS_SET_DOT, 0 },
3984Srgrimes	{ "x",		db_examine_cmd,		CS_SET_DOT, 0 },
3994Srgrimes	{ "search",	db_search_cmd,		CS_OWN|CS_SET_DOT, 0 },
4004Srgrimes	{ "set",	db_set_cmd,		CS_OWN,	0 },
4014Srgrimes	{ "write",	db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
4024Srgrimes	{ "w",		db_write_cmd,		CS_MORE|CS_SET_DOT, 0 },
4034Srgrimes	{ "delete",	db_delete_cmd,		0,	0 },
4044Srgrimes	{ "d",		db_delete_cmd,		0,	0 },
4054Srgrimes	{ "break",	db_breakpoint_cmd,	0,	0 },
4064Srgrimes	{ "dwatch",	db_deletewatch_cmd,	0,	0 },
4074Srgrimes	{ "watch",	db_watchpoint_cmd,	CS_MORE,0 },
40879573Sbsd	{ "dhwatch",	db_deletehwatch_cmd,	0,      0 },
40979573Sbsd	{ "hwatch",	db_hwatchpoint_cmd,	0,      0 },
4104Srgrimes	{ "step",	db_single_step_cmd,	0,	0 },
4114Srgrimes	{ "s",		db_single_step_cmd,	0,	0 },
4124Srgrimes	{ "continue",	db_continue_cmd,	0,	0 },
4134Srgrimes	{ "c",		db_continue_cmd,	0,	0 },
4144Srgrimes	{ "until",	db_trace_until_call_cmd,0,	0 },
4154Srgrimes	{ "next",	db_trace_until_matching_cmd,0,	0 },
4164Srgrimes	{ "match",	db_trace_until_matching_cmd,0,	0 },
4174Srgrimes	{ "trace",	db_stack_trace_cmd,	0,	0 },
418115607Sphk	{ "where",	db_stack_trace_cmd,	0,	0 },
4194Srgrimes	{ "call",	db_fncall,		CS_OWN,	0 },
4204Srgrimes	{ "show",	0,			0,	db_show_cmds },
4211147Sguido	{ "ps",		db_ps,			0,	0 },
42217848Spst	{ "gdb",	db_gdb,			0,	0 },
42385944Speter	{ "reset",	db_reset,		0,	0 },
42486998Sdd	{ "kill",	db_kill,		CS_OWN,	0 },
4254Srgrimes	{ (char *)0, }
4264Srgrimes};
4274Srgrimes
42812515Sphkstatic struct command	*db_last_command = 0;
4294Srgrimes
4307090Sbde#if 0
4314Srgrimesvoid
4324Srgrimesdb_help_cmd()
4334Srgrimes{
4344Srgrimes	struct command *cmd = db_command_table;
4354Srgrimes
4364Srgrimes	while (cmd->name != 0) {
4374Srgrimes	    db_printf("%-12s", cmd->name);
4384Srgrimes	    db_end_line();
4394Srgrimes	    cmd++;
4404Srgrimes	}
4414Srgrimes}
4427090Sbde#endif
4434Srgrimes
44433296Sbde/*
44533296Sbde * At least one non-optional command must be implemented using
44633296Sbde * DB_COMMAND() so that db_cmd_set gets created.  Here is one.
44733296Sbde */
44833296SbdeDB_COMMAND(panic, db_panic)
4496204Sphk{
4507170Sdg	panic("from debugger");
4516204Sphk}
4526204Sphk
4536204Sphkvoid
4544Srgrimesdb_command_loop()
4554Srgrimes{
4564Srgrimes	/*
4574Srgrimes	 * Initialize 'prev' and 'next' to dot.
4584Srgrimes	 */
4594Srgrimes	db_prev = db_dot;
4604Srgrimes	db_next = db_dot;
4614Srgrimes
4624Srgrimes	db_cmd_loop_done = 0;
4634Srgrimes	while (!db_cmd_loop_done) {
4644Srgrimes
4654Srgrimes	    (void) setjmp(db_jmpbuf);
4664Srgrimes	    if (db_print_position() != 0)
4674Srgrimes		db_printf("\n");
4684Srgrimes
4694Srgrimes	    db_printf("db> ");
4704Srgrimes	    (void) db_read_line();
4714Srgrimes
47218296Sbde	    db_command(&db_last_command, db_command_table,
47378161Speter		       SET_BEGIN(db_cmd_set), SET_LIMIT(db_cmd_set));
4744Srgrimes	}
4754Srgrimes}
4764Srgrimes
4774Srgrimesvoid
4784Srgrimesdb_error(s)
479103746Smarkm	const char *s;
4804Srgrimes{
4814Srgrimes	if (s)
48279884Skris	    db_printf("%s", s);
4834Srgrimes	db_flush_lex();
4844Srgrimes	longjmp(db_jmpbuf, 1);
4854Srgrimes}
4864Srgrimes
4874Srgrimes
4884Srgrimes/*
4894Srgrimes * Call random function:
4904Srgrimes * !expr(arg,arg,arg)
4914Srgrimes */
49212515Sphkstatic void
49310348Sbdedb_fncall(dummy1, dummy2, dummy3, dummy4)
49410348Sbde	db_expr_t	dummy1;
49510348Sbde	boolean_t	dummy2;
49610348Sbde	db_expr_t	dummy3;
49710348Sbde	char *		dummy4;
4984Srgrimes{
4994Srgrimes	db_expr_t	fn_addr;
50012473Sbde#define	MAXARGS		11	/* XXX only 10 are passed */
5014Srgrimes	db_expr_t	args[MAXARGS];
5024Srgrimes	int		nargs = 0;
5034Srgrimes	db_expr_t	retval;
50492756Salfred	typedef db_expr_t fcn_10args_t(db_expr_t, db_expr_t, db_expr_t,
50593009Sbde			    db_expr_t, db_expr_t, db_expr_t, db_expr_t,
50693009Sbde			    db_expr_t, db_expr_t, db_expr_t);
50712473Sbde	fcn_10args_t	*func;
5084Srgrimes	int		t;
5094Srgrimes
5104Srgrimes	if (!db_expression(&fn_addr)) {
5114Srgrimes	    db_printf("Bad function\n");
5124Srgrimes	    db_flush_lex();
5134Srgrimes	    return;
5144Srgrimes	}
51512473Sbde	func = (fcn_10args_t *)fn_addr;	/* XXX */
5164Srgrimes
5174Srgrimes	t = db_read_token();
5184Srgrimes	if (t == tLPAREN) {
5194Srgrimes	    if (db_expression(&args[0])) {
5204Srgrimes		nargs++;
5214Srgrimes		while ((t = db_read_token()) == tCOMMA) {
5224Srgrimes		    if (nargs == MAXARGS) {
5234Srgrimes			db_printf("Too many arguments\n");
5244Srgrimes			db_flush_lex();
5254Srgrimes			return;
5264Srgrimes		    }
5274Srgrimes		    if (!db_expression(&args[nargs])) {
5284Srgrimes			db_printf("Argument missing\n");
5294Srgrimes			db_flush_lex();
5304Srgrimes			return;
5314Srgrimes		    }
5324Srgrimes		    nargs++;
5334Srgrimes		}
5344Srgrimes		db_unread_token(t);
5354Srgrimes	    }
5364Srgrimes	    if (db_read_token() != tRPAREN) {
5374Srgrimes		db_printf("?\n");
5384Srgrimes		db_flush_lex();
5394Srgrimes		return;
5404Srgrimes	    }
5414Srgrimes	}
5424Srgrimes	db_skip_to_eol();
5434Srgrimes
5444Srgrimes	while (nargs < MAXARGS) {
5454Srgrimes	    args[nargs++] = 0;
5464Srgrimes	}
5474Srgrimes
5484Srgrimes	retval = (*func)(args[0], args[1], args[2], args[3], args[4],
5494Srgrimes			 args[5], args[6], args[7], args[8], args[9] );
55048407Speter	db_printf("%#lr\n", (long)retval);
5514Srgrimes}
55217848Spst
55317848Spst/* Enter GDB remote protocol debugger on the next trap. */
55417848Spst
555111017Sphkvoid	  *gdb_arg = NULL;
55646783Sphkcn_getc_t *gdb_getc;
55746783Sphkcn_putc_t *gdb_putc;
55846658Smckusick
55917848Spststatic void
56017848Spstdb_gdb (dummy1, dummy2, dummy3, dummy4)
56117848Spst	db_expr_t	dummy1;
56217848Spst	boolean_t	dummy2;
56317848Spst	db_expr_t	dummy3;
56417848Spst	char *		dummy4;
56517848Spst{
56646658Smckusick
567111017Sphk	if (gdb_arg == NULL) {
56846658Smckusick		db_printf("No gdb port enabled. Set flag 0x80 on desired port\n");
56946658Smckusick		db_printf("in your configuration file (currently sio only).\n");
57046658Smckusick		return;
57146658Smckusick	}
57217848Spst	boothowto ^= RB_GDB;
57317848Spst
57417848Spst	db_printf("Next trap will enter %s\n",
57517848Spst		   boothowto & RB_GDB ? "GDB remote protocol mode"
57617848Spst				      : "DDB debugger");
57717848Spst}
57885944Speter
57985944Speterstatic void
58086998Sdddb_kill(dummy1, dummy2, dummy3, dummy4)
58186998Sdd	db_expr_t	dummy1;
58286998Sdd	boolean_t	dummy2;
58386998Sdd	db_expr_t	dummy3;
58486998Sdd	char *		dummy4;
58586998Sdd{
58686998Sdd	db_expr_t old_radix, pid, sig;
58786998Sdd	struct proc *p;
58886998Sdd
58986998Sdd#define DB_ERROR(f)	do { db_printf f; db_flush_lex(); goto out; } while (0)
59086998Sdd
59186998Sdd	/*
59286998Sdd	 * PIDs and signal numbers are typically represented in base
59386998Sdd	 * 10, so make that the default here.  It can, of course, be
59486998Sdd	 * overridden by specifying a prefix.
59586998Sdd	 */
59686998Sdd	old_radix = db_radix;
59786998Sdd	db_radix = 10;
59886998Sdd	/* Retrieve arguments. */
59986998Sdd	if (!db_expression(&sig))
60086998Sdd		DB_ERROR(("Missing signal number\n"));
60186998Sdd	if (!db_expression(&pid))
60286998Sdd		DB_ERROR(("Missing process ID\n"));
60386998Sdd	db_skip_to_eol();
60486998Sdd	if (sig < 0 || sig > _SIG_MAXSIG)
60586998Sdd		DB_ERROR(("Signal number out of range\n"));
60686998Sdd
60786998Sdd	/*
60886998Sdd	 * Find the process in question.  allproc_lock is not needed
60986998Sdd	 * since we're in DDB.
61086998Sdd	 */
61186998Sdd	/* sx_slock(&allproc_lock); */
61286998Sdd	LIST_FOREACH(p, &allproc, p_list)
61386998Sdd	    if (p->p_pid == pid)
61486998Sdd		    break;
61586998Sdd	/* sx_sunlock(&allproc_lock); */
61686998Sdd	if (p == NULL)
61789442Smjacob		DB_ERROR(("Can't find process with pid %ld\n", (long) pid));
61886998Sdd
61986998Sdd	/* If it's already locked, bail; otherwise, do the deed. */
62086998Sdd	if (PROC_TRYLOCK(p) == 0)
62189442Smjacob		DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
62286998Sdd	else {
62386998Sdd		psignal(p, sig);
62486998Sdd		PROC_UNLOCK(p);
62586998Sdd	}
62686998Sdd
62786998Sddout:
62886998Sdd	db_radix = old_radix;
62986998Sdd#undef DB_ERROR
63086998Sdd}
63186998Sdd
63286998Sddstatic void
63385944Speterdb_reset(dummy1, dummy2, dummy3, dummy4)
63485944Speter	db_expr_t	dummy1;
63585944Speter	boolean_t	dummy2;
63685944Speter	db_expr_t	dummy3;
63785944Speter	char *		dummy4;
63885944Speter{
63985944Speter
64085944Speter	cpu_reset();
64185944Speter}
642