Annotation of src/sys/ddb/db_command.c, Revision 1.71.2.3
1.71.2.3! skrll 1: /* $NetBSD: db_command.c,v 1.71.2.1 2004/08/03 10:44:46 skrll Exp $ */
1.12 cgd 2:
1.64 simonb 3: /*
1.1 cgd 4: * Mach Operating System
5: * Copyright (c) 1991,1990 Carnegie Mellon University
6: * All Rights Reserved.
1.64 simonb 7: *
1.1 cgd 8: * Permission to use, copy, modify and distribute this software and its
9: * documentation is hereby granted, provided that both the copyright
10: * notice and this permission notice appear in all copies of the
11: * software, derivative works or modified versions, and any portions
12: * thereof, and that both notices appear in supporting documentation.
1.64 simonb 13: *
1.30 pk 14: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1.1 cgd 15: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.64 simonb 17: *
1.1 cgd 18: * Carnegie Mellon requests users of this software to return to
1.64 simonb 19: *
1.1 cgd 20: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21: * School of Computer Science
22: * Carnegie Mellon University
23: * Pittsburgh PA 15213-3890
1.64 simonb 24: *
1.1 cgd 25: * any improvements or extensions that they make and grant Carnegie the
26: * rights to redistribute these changes.
27: */
1.25 mrg 28:
1.63 lukem 29: /*
30: * Command dispatcher.
31: */
32:
33: #include <sys/cdefs.h>
1.71.2.3! skrll 34: __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.71.2.1 2004/08/03 10:44:46 skrll Exp $");
1.63 lukem 35:
1.27 tron 36: #include "opt_ddb.h"
1.69 briggs 37: #include "opt_kgdb.h"
1.40 jhawk 38: #include "opt_inet.h"
1.5 mycroft 39:
1.7 mycroft 40: #include <sys/param.h>
1.18 christos 41: #include <sys/systm.h>
1.23 scottr 42: #include <sys/reboot.h>
1.65 simonb 43: #include <sys/device.h>
44: #include <sys/malloc.h>
45: #include <sys/namei.h>
46: #include <sys/pool.h>
1.7 mycroft 47: #include <sys/proc.h>
1.36 chs 48: #include <sys/vnode.h>
1.15 gwr 49:
1.1 cgd 50: #include <machine/db_machdep.h> /* type definitions */
51:
1.58 mrg 52: #if defined(_KERNEL_OPT)
1.34 sommerfe 53: #include "opt_multiprocessor.h"
54: #endif
55: #ifdef MULTIPROCESSOR
56: #include <machine/cpu.h>
57: #endif
58:
1.1 cgd 59: #include <ddb/db_lex.h>
60: #include <ddb/db_output.h>
1.10 pk 61: #include <ddb/db_command.h>
1.16 christos 62: #include <ddb/db_break.h>
63: #include <ddb/db_watch.h>
64: #include <ddb/db_run.h>
65: #include <ddb/db_variables.h>
66: #include <ddb/db_interface.h>
67: #include <ddb/db_sym.h>
68: #include <ddb/db_extern.h>
1.1 cgd 69:
1.24 mrg 70: #include <uvm/uvm_extern.h>
1.26 jonathan 71: #include <uvm/uvm_ddb.h>
1.24 mrg 72:
1.46 jhawk 73: #include "arp.h"
74:
1.1 cgd 75: /*
1.64 simonb 76: * Results of command search.
77: */
78: #define CMD_UNIQUE 0
79: #define CMD_FOUND 1
80: #define CMD_NONE 2
81: #define CMD_AMBIGUOUS 3
82: #define CMD_HELP 4
83:
84: /*
1.1 cgd 85: * Exported global variables
86: */
87: boolean_t db_cmd_loop_done;
1.17 gwr 88: label_t *db_recover;
1.64 simonb 89: db_addr_t db_dot;
90: db_addr_t db_last_addr;
91: db_addr_t db_prev;
92: db_addr_t db_next;
1.1 cgd 93:
94: /*
95: * if 'ed' style: 'dot' is set at start of last item printed,
96: * and '+' points to next line.
97: * Otherwise: 'dot' points to next item, '..' points to last.
98: */
1.64 simonb 99: static boolean_t db_ed_style = TRUE;
100:
1.65 simonb 101: static void db_buf_print_cmd(db_expr_t, int, db_expr_t, char *);
102: static void db_cmd_list(const struct db_command *);
1.64 simonb 103: static int db_cmd_search(const char *, const struct db_command *,
104: const struct db_command **);
105: static void db_command(const struct db_command **,
106: const struct db_command *);
1.65 simonb 107: static void db_event_print_cmd(db_expr_t, int, db_expr_t, char *);
108: static void db_fncall(db_expr_t, int, db_expr_t, char *);
109: static void db_malloc_print_cmd(db_expr_t, int, db_expr_t, char *);
1.64 simonb 110: static void db_map_print_cmd(db_expr_t, int, db_expr_t, char *);
1.65 simonb 111: static void db_namecache_print_cmd(db_expr_t, int, db_expr_t, char *);
1.64 simonb 112: static void db_object_print_cmd(db_expr_t, int, db_expr_t, char *);
113: static void db_page_print_cmd(db_expr_t, int, db_expr_t, char *);
114: static void db_pool_print_cmd(db_expr_t, int, db_expr_t, char *);
115: static void db_reboot_cmd(db_expr_t, int, db_expr_t, char *);
116: static void db_sifting_cmd(db_expr_t, int, db_expr_t, char *);
117: static void db_stack_trace_cmd(db_expr_t, int, db_expr_t, char *);
118: static void db_sync_cmd(db_expr_t, int, db_expr_t, char *);
1.65 simonb 119: static void db_uvmexp_print_cmd(db_expr_t, int, db_expr_t, char *);
120: static void db_vnode_print_cmd(db_expr_t, int, db_expr_t, char *);
1.71.2.1 skrll 121: static void db_mount_print_cmd(db_expr_t, int, db_expr_t, char *);
1.64 simonb 122:
123: /*
124: * 'show' commands
125: */
126:
127: static const struct db_command db_show_all_cmds[] = {
128: { "callout", db_show_callout, 0, NULL },
129: { "procs", db_show_all_procs, 0, NULL },
130: { NULL, NULL, 0, NULL }
131: };
132:
133: static const struct db_command db_show_cmds[] = {
134: { "all", NULL, 0, db_show_all_cmds },
135: #if defined(INET) && (NARP > 0)
136: { "arptab", db_show_arptab, 0, NULL },
137: #endif
138: { "breaks", db_listbreak_cmd, 0, NULL },
139: { "buf", db_buf_print_cmd, 0, NULL },
1.65 simonb 140: { "event", db_event_print_cmd, 0, NULL },
141: { "malloc", db_malloc_print_cmd, 0, NULL },
1.64 simonb 142: { "map", db_map_print_cmd, 0, NULL },
1.71.2.1 skrll 143: { "mount", db_mount_print_cmd, 0, NULL },
1.64 simonb 144: { "ncache", db_namecache_print_cmd, 0, NULL },
145: { "object", db_object_print_cmd, 0, NULL },
146: { "page", db_page_print_cmd, 0, NULL },
147: { "pool", db_pool_print_cmd, 0, NULL },
148: { "registers", db_show_regs, 0, NULL },
1.71.2.1 skrll 149: { "sched_qs", db_show_sched_qs, 0, NULL },
1.64 simonb 150: { "uvmexp", db_uvmexp_print_cmd, 0, NULL },
151: { "vnode", db_vnode_print_cmd, 0, NULL },
152: { "watches", db_listwatch_cmd, 0, NULL },
153: { NULL, NULL, 0, NULL }
154: };
155:
156: static const struct db_command db_command_table[] = {
1.71.2.1 skrll 157: { "b", db_breakpoint_cmd, 0, NULL },
1.64 simonb 158: { "break", db_breakpoint_cmd, 0, NULL },
1.68 jmc 159: { "bt", db_stack_trace_cmd, 0, NULL },
1.64 simonb 160: { "c", db_continue_cmd, 0, NULL },
161: { "call", db_fncall, CS_OWN, NULL },
162: { "callout", db_show_callout, 0, NULL },
163: { "continue", db_continue_cmd, 0, NULL },
164: { "d", db_delete_cmd, 0, NULL },
165: { "delete", db_delete_cmd, 0, NULL },
166: { "dmesg", db_dmesg, 0, NULL },
167: { "dwatch", db_deletewatch_cmd, 0, NULL },
168: { "examine", db_examine_cmd, CS_SET_DOT, NULL },
169: { "kill", db_kill_proc, CS_OWN, NULL },
1.69 briggs 170: #ifdef KGDB
171: { "kgdb", db_kgdb_cmd, 0, NULL },
172: #endif
1.64 simonb 173: #ifdef DB_MACHINE_COMMANDS
174: { "machine", NULL, 0, db_machine_command_table },
175: #endif
176: { "match", db_trace_until_matching_cmd,0, NULL },
177: { "next", db_trace_until_matching_cmd,0, NULL },
178: { "p", db_print_cmd, 0, NULL },
179: { "print", db_print_cmd, 0, NULL },
180: { "ps", db_show_all_procs, 0, NULL },
181: { "reboot", db_reboot_cmd, CS_OWN, NULL },
182: { "s", db_single_step_cmd, 0, NULL },
183: { "search", db_search_cmd, CS_OWN|CS_SET_DOT, NULL },
184: { "set", db_set_cmd, CS_OWN, NULL },
185: { "show", NULL, 0, db_show_cmds },
186: { "sifting", db_sifting_cmd, CS_OWN, NULL },
187: { "step", db_single_step_cmd, 0, NULL },
188: { "sync", db_sync_cmd, CS_OWN, NULL },
189: { "trace", db_stack_trace_cmd, 0, NULL },
190: { "until", db_trace_until_call_cmd,0, NULL },
191: { "w", db_write_cmd, CS_MORE|CS_SET_DOT, NULL },
192: { "watch", db_watchpoint_cmd, CS_MORE, NULL },
193: { "write", db_write_cmd, CS_MORE|CS_SET_DOT, NULL },
194: { "x", db_examine_cmd, CS_SET_DOT, NULL },
195: { NULL, NULL, 0, NULL }
196: };
197:
198: static const struct db_command *db_last_command = NULL;
1.1 cgd 199:
200: /*
201: * Utility routine - discard tokens through end-of-line.
202: */
203: void
1.64 simonb 204: db_skip_to_eol(void)
1.1 cgd 205: {
1.64 simonb 206: int t;
207:
1.1 cgd 208: do {
1.64 simonb 209: t = db_read_token();
1.1 cgd 210: } while (t != tEOL);
211: }
212:
1.64 simonb 213: void
214: db_error(s)
215: char *s;
216: {
217:
218: if (s)
219: db_printf("%s", s);
220: db_flush_lex();
221: longjmp(db_recover);
222: }
223:
224: void
225: db_command_loop(void)
226: {
227: label_t db_jmpbuf;
228: label_t *savejmp;
229:
230: /*
231: * Initialize 'prev' and 'next' to dot.
232: */
233: db_prev = db_dot;
234: db_next = db_dot;
235:
236: db_cmd_loop_done = 0;
237:
238: savejmp = db_recover;
239: db_recover = &db_jmpbuf;
240: (void) setjmp(&db_jmpbuf);
241:
242: while (!db_cmd_loop_done) {
243: if (db_print_position() != 0)
244: db_printf("\n");
245: db_output_line = 0;
246:
247:
248: #ifdef MULTIPROCESSOR
249: db_printf("db{%ld}> ", (long)cpu_number());
250: #else
251: db_printf("db> ");
252: #endif
253: (void) db_read_line();
254:
255: db_command(&db_last_command, db_command_table);
256: }
257:
258: db_recover = savejmp;
259: }
1.1 cgd 260:
261: /*
262: * Search for command prefix.
263: */
1.64 simonb 264: static int
265: db_cmd_search(const char *name, const struct db_command *table,
266: const struct db_command **cmdp)
1.1 cgd 267: {
1.53 jdolecek 268: const struct db_command *cmd;
1.10 pk 269: int result = CMD_NONE;
1.1 cgd 270:
271: for (cmd = table; cmd->name != 0; cmd++) {
1.64 simonb 272: const char *lp;
273: const char *rp;
274: int c;
275:
276: lp = name;
277: rp = cmd->name;
278: while ((c = *lp) == *rp) {
279: if (c == 0) {
280: /* complete match */
281: *cmdp = cmd;
282: return (CMD_UNIQUE);
283: }
284: lp++;
285: rp++;
286: }
1.1 cgd 287: if (c == 0) {
1.64 simonb 288: /* end of name, not end of command -
289: partial match */
290: if (result == CMD_FOUND) {
291: result = CMD_AMBIGUOUS;
292: /* but keep looking for a full match -
293: this lets us match single letters */
294: } else {
295: *cmdp = cmd;
296: result = CMD_FOUND;
297: }
1.1 cgd 298: }
299: }
300: if (result == CMD_NONE) {
1.64 simonb 301: /* check for 'help' */
1.1 cgd 302: if (name[0] == 'h' && name[1] == 'e'
303: && name[2] == 'l' && name[3] == 'p')
304: result = CMD_HELP;
305: }
306: return (result);
307: }
308:
1.64 simonb 309: static void
310: db_cmd_list(const struct db_command *table)
1.1 cgd 311: {
1.67 simonb 312: int i, j, w, columns, lines, width=0, numcmds;
1.53 jdolecek 313: const char *p;
1.1 cgd 314:
1.32 lukem 315: for (numcmds = 0; table[numcmds].name != NULL; numcmds++) {
316: w = strlen(table[numcmds].name);
317: if (w > width)
318: width = w;
319: }
320: width = DB_NEXT_TAB(width);
321:
322: columns = db_max_width / width;
323: if (columns == 0)
324: columns = 1;
325: lines = (numcmds + columns - 1) / columns;
326: for (i = 0; i < lines; i++) {
327: for (j = 0; j < columns; j++) {
328: p = table[j * lines + i].name;
329: if (p)
330: db_printf("%s", p);
331: if (j * lines + i + lines >= numcmds) {
332: db_putchar('\n');
333: break;
334: }
335: w = strlen(p);
336: while (w < width) {
337: w = DB_NEXT_TAB(w);
338: db_putchar('\t');
339: }
340: }
1.1 cgd 341: }
342: }
343:
1.64 simonb 344: static void
345: db_command(const struct db_command **last_cmdp,
346: const struct db_command *cmd_table)
1.1 cgd 347: {
1.53 jdolecek 348: const struct db_command *cmd;
1.1 cgd 349: int t;
350: char modif[TOK_STRING_SIZE];
351: db_expr_t addr, count;
1.16 christos 352: boolean_t have_addr = FALSE;
1.1 cgd 353: int result;
354:
1.64 simonb 355: static db_expr_t last_count = 0;
1.38 jhawk 356:
1.1 cgd 357: t = db_read_token();
1.38 jhawk 358: if ((t == tEOL) || (t == tCOMMA)) {
1.1 cgd 359: /*
1.64 simonb 360: * An empty line repeats last command, at 'next'.
361: * Only a count repeats the last command with the new count.
362: */
363: cmd = *last_cmdp;
364: addr = (db_expr_t)db_next;
365: if (t == tCOMMA) {
366: if (!db_expression(&count)) {
367: db_printf("Count missing\n");
368: db_flush_lex();
369: return;
370: }
371: } else
372: count = last_count;
373: have_addr = FALSE;
374: modif[0] = '\0';
375: db_skip_to_eol();
376: } else if (t == tEXCL) {
377: db_fncall(0, 0, 0, NULL);
378: return;
379: } else if (t != tIDENT) {
380: db_printf("?\n");
381: db_flush_lex();
382: return;
383: } else {
384: /*
385: * Search for command
1.1 cgd 386: */
1.64 simonb 387: while (cmd_table) {
388: result = db_cmd_search(db_tok_string, cmd_table, &cmd);
389: switch (result) {
390: case CMD_NONE:
391: db_printf("No such command\n");
392: db_flush_lex();
393: return;
394: case CMD_AMBIGUOUS:
395: db_printf("Ambiguous\n");
396: db_flush_lex();
397: return;
398: case CMD_HELP:
399: db_cmd_list(cmd_table);
400: db_flush_lex();
401: return;
402: default:
403: break;
404: }
405: if ((cmd_table = cmd->more) != 0) {
406: t = db_read_token();
407: if (t != tIDENT) {
408: db_cmd_list(cmd_table);
409: db_flush_lex();
410: return;
411: }
412: }
1.1 cgd 413: }
414:
1.64 simonb 415: if ((cmd->flag & CS_OWN) == 0) {
416: /*
417: * Standard syntax:
418: * command [/modifier] [addr] [,count]
419: */
420: t = db_read_token();
421: if (t == tSLASH) {
422: t = db_read_token();
423: if (t != tIDENT) {
424: db_printf("Bad modifier\n");
425: db_flush_lex();
426: return;
427: }
1.71 itojun 428: strlcpy(modif, db_tok_string, sizeof(modif));
1.64 simonb 429: } else {
430: db_unread_token(t);
431: modif[0] = '\0';
432: }
433:
434: if (db_expression(&addr)) {
435: db_dot = (db_addr_t) addr;
436: db_last_addr = db_dot;
437: have_addr = TRUE;
438: } else {
439: addr = (db_expr_t) db_dot;
440: have_addr = FALSE;
441: }
442: t = db_read_token();
443: if (t == tCOMMA) {
444: if (!db_expression(&count)) {
445: db_printf("Count missing\n");
446: db_flush_lex();
447: return;
448: }
449: } else {
450: db_unread_token(t);
451: count = -1;
452: }
453: if ((cmd->flag & CS_MORE) == 0) {
454: db_skip_to_eol();
455: }
1.1 cgd 456: }
457: }
458: *last_cmdp = cmd;
1.38 jhawk 459: last_count = count;
1.1 cgd 460: if (cmd != 0) {
461: /*
1.64 simonb 462: * Execute the command.
1.1 cgd 463: */
1.64 simonb 464: (*cmd->fcn)(addr, have_addr, count, modif);
465:
466: if (cmd->flag & CS_SET_DOT) {
467: /*
468: * If command changes dot, set dot to
469: * previous address displayed (if 'ed' style).
470: */
471: if (db_ed_style)
472: db_dot = db_prev;
473: else
474: db_dot = db_next;
475: } else {
476: /*
477: * If command does not change dot,
478: * set 'next' location to be the same.
479: */
480: db_next = db_dot;
1.1 cgd 481: }
482: }
483: }
484:
1.4 brezak 485: /*ARGSUSED*/
1.64 simonb 486: static void
487: db_map_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
488: {
489: boolean_t full = FALSE;
490:
491: if (modif[0] == 'f')
492: full = TRUE;
1.60 matt 493:
494: if (have_addr == FALSE)
1.66 scw 495: addr = (db_expr_t)(intptr_t) kernel_map;
1.4 brezak 496:
1.66 scw 497: uvm_map_printit((struct vm_map *)(intptr_t) addr, full, db_printf);
1.4 brezak 498: }
499:
500: /*ARGSUSED*/
1.64 simonb 501: static void
502: db_malloc_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.62 thorpej 503: {
1.64 simonb 504:
1.62 thorpej 505: #ifdef MALLOC_DEBUG
506: if (!have_addr)
507: addr = 0;
508:
509: debug_malloc_printit(db_printf, (vaddr_t) addr);
510: #else
511: db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
512: #endif /* MALLOC_DEBUG */
513: }
514:
515: /*ARGSUSED*/
1.64 simonb 516: static void
517: db_object_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
518: {
519: boolean_t full = FALSE;
520:
521: if (modif[0] == 'f')
522: full = TRUE;
1.4 brezak 523:
1.66 scw 524: uvm_object_printit((struct uvm_object *)(intptr_t) addr, full,
525: db_printf);
1.24 mrg 526: }
527:
528: /*ARGSUSED*/
1.64 simonb 529: static void
530: db_page_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
531: {
532: boolean_t full = FALSE;
533:
534: if (modif[0] == 'f')
535: full = TRUE;
1.24 mrg 536:
1.66 scw 537: uvm_page_printit((struct vm_page *)(intptr_t) addr, full, db_printf);
1.36 chs 538: }
539:
540: /*ARGSUSED*/
1.64 simonb 541: static void
542: db_buf_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.36 chs 543: {
544: boolean_t full = FALSE;
1.64 simonb 545:
1.36 chs 546: if (modif[0] == 'f')
547: full = TRUE;
548:
1.66 scw 549: vfs_buf_print((struct buf *)(intptr_t) addr, full, db_printf);
1.65 simonb 550: }
551:
552: /*ARGSUSED*/
553: static void
554: db_event_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
555: {
556: boolean_t full = FALSE;
557:
558: if (modif[0] == 'f')
559: full = TRUE;
560:
561: event_print(full, db_printf);
1.36 chs 562: }
563:
564: /*ARGSUSED*/
1.64 simonb 565: static void
566: db_vnode_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.36 chs 567: {
568: boolean_t full = FALSE;
1.64 simonb 569:
1.36 chs 570: if (modif[0] == 'f')
571: full = TRUE;
572:
1.66 scw 573: vfs_vnode_print((struct vnode *)(intptr_t) addr, full, db_printf);
1.4 brezak 574: }
575:
1.71.2.1 skrll 576: static void
577: db_mount_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
578: {
579: boolean_t full = FALSE;
580:
581: if (modif[0] == 'f')
582: full = TRUE;
583:
584: vfs_mount_print((struct mount *)(intptr_t) addr, full, db_printf);
585: }
586:
1.31 thorpej 587: /*ARGSUSED*/
1.64 simonb 588: static void
589: db_pool_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.31 thorpej 590: {
1.64 simonb 591:
1.66 scw 592: pool_printit((struct pool *)(intptr_t) addr, modif, db_printf);
1.51 chs 593: }
1.31 thorpej 594:
1.51 chs 595: /*ARGSUSED*/
1.64 simonb 596: static void
597: db_namecache_print_cmd(db_expr_t addr, int have_addr, db_expr_t count,
598: char *modif)
1.51 chs 599: {
1.64 simonb 600:
1.66 scw 601: namecache_print((struct vnode *)(intptr_t) addr, db_printf);
1.51 chs 602: }
603:
604: /*ARGSUSED*/
1.64 simonb 605: static void
606: db_uvmexp_print_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.51 chs 607: {
1.64 simonb 608:
1.51 chs 609: uvmexp_print(db_printf);
1.31 thorpej 610: }
611:
1.1 cgd 612: /*
613: * Call random function:
614: * !expr(arg,arg,arg)
615: */
1.16 christos 616: /*ARGSUSED*/
1.64 simonb 617: static void
618: db_fncall(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.1 cgd 619: {
620: db_expr_t fn_addr;
621: #define MAXARGS 11
622: db_expr_t args[MAXARGS];
623: int nargs = 0;
624: db_expr_t retval;
1.64 simonb 625: db_expr_t (*func)(db_expr_t, ...);
1.1 cgd 626: int t;
627:
628: if (!db_expression(&fn_addr)) {
1.64 simonb 629: db_printf("Bad function\n");
630: db_flush_lex();
631: return;
1.1 cgd 632: }
1.66 scw 633: func = (db_expr_t (*)(db_expr_t, ...))(intptr_t) fn_addr;
1.1 cgd 634:
635: t = db_read_token();
636: if (t == tLPAREN) {
1.64 simonb 637: if (db_expression(&args[0])) {
638: nargs++;
639: while ((t = db_read_token()) == tCOMMA) {
640: if (nargs == MAXARGS) {
641: db_printf("Too many arguments\n");
642: db_flush_lex();
643: return;
644: }
645: if (!db_expression(&args[nargs])) {
646: db_printf("Argument missing\n");
647: db_flush_lex();
648: return;
649: }
650: nargs++;
651: }
652: db_unread_token(t);
653: }
654: if (db_read_token() != tRPAREN) {
655: db_printf("?\n");
1.1 cgd 656: db_flush_lex();
657: return;
658: }
659: }
660: db_skip_to_eol();
661:
662: while (nargs < MAXARGS) {
1.64 simonb 663: args[nargs++] = 0;
1.1 cgd 664: }
665:
666: retval = (*func)(args[0], args[1], args[2], args[3], args[4],
1.20 christos 667: args[5], args[6], args[7], args[8], args[9]);
1.45 jhawk 668: db_printf("%s\n", db_num_to_str(retval));
1.23 scottr 669: }
670:
1.64 simonb 671: static void
672: db_reboot_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.23 scottr 673: {
674: db_expr_t bootflags;
675:
676: /* Flags, default to RB_AUTOBOOT */
677: if (!db_expression(&bootflags))
678: bootflags = (db_expr_t)RB_AUTOBOOT;
679: if (db_read_token() != tEOL) {
1.64 simonb 680: db_error("?\n");
681: /*NOTREACHED*/
1.23 scottr 682: }
1.47 sommerfe 683: /*
684: * We are leaving DDB, never to return upward.
685: * Clear db_recover so that we can debug faults in functions
686: * called from cpu_reboot.
687: */
688: db_recover = 0;
1.23 scottr 689: cpu_reboot((int)bootflags, NULL);
1.41 jhawk 690: }
691:
1.64 simonb 692: static void
693: db_sifting_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.41 jhawk 694: {
695: int mode, t;
696:
697: t = db_read_token();
698: if (t == tSLASH) {
699: t = db_read_token();
700: if (t != tIDENT) {
701: bad_modifier:
702: db_printf("Bad modifier\n");
703: db_flush_lex();
704: return;
705: }
706: if (!strcmp(db_tok_string, "F"))
707: mode = 'F';
708: else
709: goto bad_modifier;
710: t = db_read_token();
711: } else
712: mode = 0;
713:
1.51 chs 714: if (t == tIDENT)
1.41 jhawk 715: db_sifting(db_tok_string, mode);
716: else {
717: db_printf("Bad argument (non-string)\n");
718: db_flush_lex();
719: }
1.43 jhawk 720: }
721:
1.64 simonb 722: static void
723: db_stack_trace_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.43 jhawk 724: {
1.70 atatat 725: register char *cp = modif;
726: register char c;
727: void (*pr)(const char *, ...);
728:
729: pr = db_printf;
730: while ((c = *cp++) != 0)
731: if (c == 'l')
732: pr = printf;
1.64 simonb 733:
1.43 jhawk 734: if (count == -1)
735: count = 65535;
736:
1.70 atatat 737: db_stack_trace_print(addr, have_addr, count, modif, pr);
1.32 lukem 738: }
739:
1.64 simonb 740: static void
741: db_sync_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
1.32 lukem 742: {
1.64 simonb 743:
1.47 sommerfe 744: /*
745: * We are leaving DDB, never to return upward.
746: * Clear db_recover so that we can debug faults in functions
747: * called from cpu_reboot.
748: */
749: db_recover = 0;
1.32 lukem 750: cpu_reboot(RB_DUMP, NULL);
1.1 cgd 751: }
CVSweb <webmaster@jp.NetBSD.org>