db_command.c (177615) | db_command.c (183054) |
---|---|
1/*- 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the --- 18 unchanged lines hidden (view full) --- 27 * Author: David B. Golub, Carnegie Mellon University 28 * Date: 7/90 29 */ 30/* 31 * Command dispatcher. 32 */ 33 34#include <sys/cdefs.h> | 1/*- 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the --- 18 unchanged lines hidden (view full) --- 27 * Author: David B. Golub, Carnegie Mellon University 28 * Date: 7/90 29 */ 30/* 31 * Command dispatcher. 32 */ 33 34#include <sys/cdefs.h> |
35__FBSDID("$FreeBSD: head/sys/ddb/db_command.c 177615 2008-03-25 20:36:32Z sam $"); | 35__FBSDID("$FreeBSD: head/sys/ddb/db_command.c 183054 2008-09-15 22:45:14Z sam $"); |
36 37#include <sys/param.h> 38#include <sys/linker_set.h> 39#include <sys/lock.h> 40#include <sys/kdb.h> 41#include <sys/mutex.h> 42#include <sys/proc.h> 43#include <sys/reboot.h> 44#include <sys/signalvar.h> 45#include <sys/systm.h> 46#include <sys/cons.h> 47#include <sys/watchdog.h> | 36 37#include <sys/param.h> 38#include <sys/linker_set.h> 39#include <sys/lock.h> 40#include <sys/kdb.h> 41#include <sys/mutex.h> 42#include <sys/proc.h> 43#include <sys/reboot.h> 44#include <sys/signalvar.h> 45#include <sys/systm.h> 46#include <sys/cons.h> 47#include <sys/watchdog.h> |
48#include <sys/kernel.h> |
|
48 49#include <ddb/ddb.h> 50#include <ddb/db_command.h> 51#include <ddb/db_lex.h> 52#include <ddb/db_output.h> 53 54#include <machine/cpu.h> 55#include <machine/setjmp.h> 56 57/* 58 * Exported global variables 59 */ 60boolean_t db_cmd_loop_done; 61db_addr_t db_dot; 62db_addr_t db_last_addr; 63db_addr_t db_prev; 64db_addr_t db_next; 65 | 49 50#include <ddb/ddb.h> 51#include <ddb/db_command.h> 52#include <ddb/db_lex.h> 53#include <ddb/db_output.h> 54 55#include <machine/cpu.h> 56#include <machine/setjmp.h> 57 58/* 59 * Exported global variables 60 */ 61boolean_t db_cmd_loop_done; 62db_addr_t db_dot; 63db_addr_t db_last_addr; 64db_addr_t db_prev; 65db_addr_t db_next; 66 |
66SET_DECLARE(db_cmd_set, struct command); 67SET_DECLARE(db_show_cmd_set, struct command); 68SET_DECLARE(db_show_all_cmd_set, struct command); 69 | |
70static db_cmdfcn_t db_fncall; 71static db_cmdfcn_t db_gdb; 72static db_cmdfcn_t db_halt; 73static db_cmdfcn_t db_kill; 74static db_cmdfcn_t db_reset; 75static db_cmdfcn_t db_stack_trace; 76static db_cmdfcn_t db_stack_trace_all; 77static db_cmdfcn_t db_watchdog; 78 79/* 80 * 'show' commands 81 */ 82 83static struct command db_show_all_cmds[] = { | 67static db_cmdfcn_t db_fncall; 68static db_cmdfcn_t db_gdb; 69static db_cmdfcn_t db_halt; 70static db_cmdfcn_t db_kill; 71static db_cmdfcn_t db_reset; 72static db_cmdfcn_t db_stack_trace; 73static db_cmdfcn_t db_stack_trace_all; 74static db_cmdfcn_t db_watchdog; 75 76/* 77 * 'show' commands 78 */ 79 80static struct command db_show_all_cmds[] = { |
84 { (char *)0 } | 81 { "trace", db_stack_trace_all, 0, 0 }, |
85}; | 82}; |
83struct command_table db_show_all_table = 84 LIST_HEAD_INITIALIZER(db_show_all_table); |
|
86 | 85 |
87static struct command_table db_show_all_table = { 88 db_show_all_cmds, 89 SET_BEGIN(db_show_all_cmd_set), 90 SET_LIMIT(db_show_all_cmd_set) 91}; 92 | |
93static struct command db_show_cmds[] = { 94 { "all", 0, 0, &db_show_all_table }, 95 { "registers", db_show_regs, 0, 0 }, 96 { "breaks", db_listbreak_cmd, 0, 0 }, 97 { "threads", db_show_threads, 0, 0 }, | 86static struct command db_show_cmds[] = { 87 { "all", 0, 0, &db_show_all_table }, 88 { "registers", db_show_regs, 0, 0 }, 89 { "breaks", db_listbreak_cmd, 0, 0 }, 90 { "threads", db_show_threads, 0, 0 }, |
98 { (char *)0, } | |
99}; | 91}; |
92struct command_table db_show_table = LIST_HEAD_INITIALIZER(db_show_table); |
|
100 | 93 |
101static struct command_table db_show_table = { 102 db_show_cmds, 103 SET_BEGIN(db_show_cmd_set), 104 SET_LIMIT(db_show_cmd_set) 105}; 106 107static struct command db_commands[] = { | 94static struct command db_cmds[] = { |
108 { "print", db_print_cmd, 0, 0 }, 109 { "p", db_print_cmd, 0, 0 }, 110 { "examine", db_examine_cmd, CS_SET_DOT, 0 }, 111 { "x", db_examine_cmd, CS_SET_DOT, 0 }, 112 { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, 113 { "set", db_set_cmd, CS_OWN, 0 }, 114 { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, 115 { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, --- 9 unchanged lines hidden (view full) --- 125 { "s", db_single_step_cmd, 0, 0 }, 126 { "continue", db_continue_cmd, 0, 0 }, 127 { "c", db_continue_cmd, 0, 0 }, 128 { "until", db_trace_until_call_cmd,0, 0 }, 129 { "next", db_trace_until_matching_cmd,0, 0 }, 130 { "match", db_trace_until_matching_cmd,0, 0 }, 131 { "trace", db_stack_trace, CS_OWN, 0 }, 132 { "t", db_stack_trace, CS_OWN, 0 }, | 95 { "print", db_print_cmd, 0, 0 }, 96 { "p", db_print_cmd, 0, 0 }, 97 { "examine", db_examine_cmd, CS_SET_DOT, 0 }, 98 { "x", db_examine_cmd, CS_SET_DOT, 0 }, 99 { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, 100 { "set", db_set_cmd, CS_OWN, 0 }, 101 { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, 102 { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, --- 9 unchanged lines hidden (view full) --- 112 { "s", db_single_step_cmd, 0, 0 }, 113 { "continue", db_continue_cmd, 0, 0 }, 114 { "c", db_continue_cmd, 0, 0 }, 115 { "until", db_trace_until_call_cmd,0, 0 }, 116 { "next", db_trace_until_matching_cmd,0, 0 }, 117 { "match", db_trace_until_matching_cmd,0, 0 }, 118 { "trace", db_stack_trace, CS_OWN, 0 }, 119 { "t", db_stack_trace, CS_OWN, 0 }, |
120 /* XXX alias for all trace */ |
|
133 { "alltrace", db_stack_trace_all, 0, 0 }, 134 { "where", db_stack_trace, CS_OWN, 0 }, 135 { "bt", db_stack_trace, CS_OWN, 0 }, 136 { "call", db_fncall, CS_OWN, 0 }, 137 { "show", 0, 0, &db_show_table }, 138 { "ps", db_ps, 0, 0 }, 139 { "gdb", db_gdb, 0, 0 }, 140 { "halt", db_halt, 0, 0 }, 141 { "reboot", db_reset, 0, 0 }, 142 { "reset", db_reset, 0, 0 }, 143 { "kill", db_kill, CS_OWN, 0 }, 144 { "watchdog", db_watchdog, 0, 0 }, 145 { "thread", db_set_thread, CS_OWN, 0 }, 146 { "run", db_run_cmd, CS_OWN, 0 }, 147 { "script", db_script_cmd, CS_OWN, 0 }, 148 { "scripts", db_scripts_cmd, 0, 0 }, 149 { "unscript", db_unscript_cmd, CS_OWN, 0 }, 150 { "capture", db_capture_cmd, CS_OWN, 0 }, 151 { "textdump", db_textdump_cmd, CS_OWN, 0 }, | 121 { "alltrace", db_stack_trace_all, 0, 0 }, 122 { "where", db_stack_trace, CS_OWN, 0 }, 123 { "bt", db_stack_trace, CS_OWN, 0 }, 124 { "call", db_fncall, CS_OWN, 0 }, 125 { "show", 0, 0, &db_show_table }, 126 { "ps", db_ps, 0, 0 }, 127 { "gdb", db_gdb, 0, 0 }, 128 { "halt", db_halt, 0, 0 }, 129 { "reboot", db_reset, 0, 0 }, 130 { "reset", db_reset, 0, 0 }, 131 { "kill", db_kill, CS_OWN, 0 }, 132 { "watchdog", db_watchdog, 0, 0 }, 133 { "thread", db_set_thread, CS_OWN, 0 }, 134 { "run", db_run_cmd, CS_OWN, 0 }, 135 { "script", db_script_cmd, CS_OWN, 0 }, 136 { "scripts", db_scripts_cmd, 0, 0 }, 137 { "unscript", db_unscript_cmd, CS_OWN, 0 }, 138 { "capture", db_capture_cmd, CS_OWN, 0 }, 139 { "textdump", db_textdump_cmd, CS_OWN, 0 }, |
152 { (char *)0, } | |
153}; | 140}; |
141struct command_table db_cmd_table = LIST_HEAD_INITIALIZER(db_cmd_table); |
|
154 | 142 |
155static struct command_table db_command_table = { 156 db_commands, 157 SET_BEGIN(db_cmd_set), 158 SET_LIMIT(db_cmd_set) 159}; 160 | |
161static struct command *db_last_command = 0; 162 163/* 164 * if 'ed' style: 'dot' is set at start of last item printed, 165 * and '+' points to next line. 166 * Otherwise: 'dot' points to next item, '..' points to last. 167 */ 168static boolean_t db_ed_style = TRUE; --- 23 unchanged lines hidden (view full) --- 192 struct command **cmdp, int *resultp); 193static void db_cmd_list(struct command_table *table); 194static int db_cmd_search(char *name, struct command_table *table, 195 struct command **cmdp); 196static void db_command(struct command **last_cmdp, 197 struct command_table *cmd_table, int dopager); 198 199/* | 143static struct command *db_last_command = 0; 144 145/* 146 * if 'ed' style: 'dot' is set at start of last item printed, 147 * and '+' points to next line. 148 * Otherwise: 'dot' points to next item, '..' points to last. 149 */ 150static boolean_t db_ed_style = TRUE; --- 23 unchanged lines hidden (view full) --- 174 struct command **cmdp, int *resultp); 175static void db_cmd_list(struct command_table *table); 176static int db_cmd_search(char *name, struct command_table *table, 177 struct command **cmdp); 178static void db_command(struct command **last_cmdp, 179 struct command_table *cmd_table, int dopager); 180 181/* |
182 * Initialize the command lists from the static tables. 183 */ 184static void 185db_cmd_init(void) 186{ 187#define N(a) (sizeof(a) / sizeof(a[0])) 188 int i; 189 190 for (i = 0; i < N(db_cmds); i++) 191 db_command_register(&db_cmd_table, &db_cmds[i]); 192 for (i = 0; i < N(db_show_cmds); i++) 193 db_command_register(&db_show_table, &db_show_cmds[i]); 194 for (i = 0; i < N(db_show_all_cmds); i++) 195 db_command_register(&db_show_all_table, &db_show_all_cmds[i]); 196#undef N 197} 198SYSINIT(_cmd_init, SI_SUB_KLD, SI_ORDER_FIRST, db_cmd_init, NULL); 199 200/* 201 * Register a command. 202 */ 203void 204db_command_register(struct command_table *list, struct command *cmd) 205{ 206 struct command *c, *last; 207 208 last = NULL; 209 LIST_FOREACH(c, list, next) { 210 int n = strcmp(cmd->name, c->name); 211 212 /* Check that the command is not already present. */ 213 if (n == 0) { 214 printf("%s: Warning, the command \"%s\" already exists;" 215 " ignoring request\n", __func__, cmd->name); 216 return; 217 } 218 if (n < 0) { 219 /* NB: keep list sorted lexicographically */ 220 LIST_INSERT_BEFORE(c, cmd, next); 221 return; 222 } 223 last = c; 224 } 225 if (last == NULL) 226 LIST_INSERT_HEAD(list, cmd, next); 227 else 228 LIST_INSERT_AFTER(last, cmd, next); 229} 230 231/* 232 * Remove a command previously registered with db_command_register. 233 */ 234void 235db_command_unregister(struct command_table *list, struct command *cmd) 236{ 237 struct command *c; 238 239 LIST_FOREACH(c, list, next) { 240 if (cmd == c) { 241 LIST_REMOVE(cmd, next); 242 return; 243 } 244 } 245 /* NB: intentionally quiet */ 246} 247 248/* |
|
200 * Helper function to match a single command. 201 */ 202static void 203db_cmd_match(name, cmd, cmdp, resultp) 204 char * name; 205 struct command *cmd; 206 struct command **cmdp; /* out */ 207 int * resultp; --- 32 unchanged lines hidden (view full) --- 240 */ 241static int 242db_cmd_search(name, table, cmdp) 243 char * name; 244 struct command_table *table; 245 struct command **cmdp; /* out */ 246{ 247 struct command *cmd; | 249 * Helper function to match a single command. 250 */ 251static void 252db_cmd_match(name, cmd, cmdp, resultp) 253 char * name; 254 struct command *cmd; 255 struct command **cmdp; /* out */ 256 int * resultp; --- 32 unchanged lines hidden (view full) --- 289 */ 290static int 291db_cmd_search(name, table, cmdp) 292 char * name; 293 struct command_table *table; 294 struct command **cmdp; /* out */ 295{ 296 struct command *cmd; |
248 struct command **aux_cmdp; | |
249 int result = CMD_NONE; 250 | 297 int result = CMD_NONE; 298 |
251 for (cmd = table->table; cmd->name != 0; cmd++) { 252 db_cmd_match(name, cmd, cmdp, &result); | 299 LIST_FOREACH(cmd, table, next) { 300 db_cmd_match(name,cmd,cmdp,&result); |
253 if (result == CMD_UNIQUE) | 301 if (result == CMD_UNIQUE) |
254 return (CMD_UNIQUE); | 302 break; |
255 } | 303 } |
256 if (table->aux_tablep != NULL) 257 for (aux_cmdp = table->aux_tablep; 258 aux_cmdp < table->aux_tablep_end; 259 aux_cmdp++) { 260 db_cmd_match(name, *aux_cmdp, cmdp, &result); 261 if (result == CMD_UNIQUE) 262 return (CMD_UNIQUE); 263 } | 304 |
264 if (result == CMD_NONE) { 265 /* check for 'help' */ 266 if (name[0] == 'h' && name[1] == 'e' 267 && name[2] == 'l' && name[3] == 'p') 268 result = CMD_HELP; 269 } 270 return (result); 271} 272 273static void 274db_cmd_list(table) 275 struct command_table *table; 276{ | 305 if (result == CMD_NONE) { 306 /* check for 'help' */ 307 if (name[0] == 'h' && name[1] == 'e' 308 && name[2] == 'l' && name[3] == 'p') 309 result = CMD_HELP; 310 } 311 return (result); 312} 313 314static void 315db_cmd_list(table) 316 struct command_table *table; 317{ |
277 register struct command *cmd; 278 register struct command **aux_cmdp; | 318 register struct command *cmd; |
279 | 319 |
280 for (cmd = table->table; cmd->name != 0; cmd++) { 281 db_printf("%-12s", cmd->name); 282 db_end_line(12); | 320 LIST_FOREACH(cmd, table, next) { 321 db_printf("%-12s", cmd->name); 322 db_end_line(12); |
283 } | 323 } |
284 if (table->aux_tablep == NULL) 285 return; 286 for (aux_cmdp = table->aux_tablep; aux_cmdp < table->aux_tablep_end; 287 aux_cmdp++) { 288 db_printf("%-12s", (*aux_cmdp)->name); 289 db_end_line(12); 290 } | |
291} 292 293static void 294db_command(last_cmdp, cmd_table, dopager) 295 struct command **last_cmdp; /* IN_OUT */ 296 struct command_table *cmd_table; 297 int dopager; 298{ | 324} 325 326static void 327db_command(last_cmdp, cmd_table, dopager) 328 struct command **last_cmdp; /* IN_OUT */ 329 struct command_table *cmd_table; 330 int dopager; 331{ |
299 struct command *cmd; | 332 struct command *cmd = NULL; |
300 int t; 301 char modif[TOK_STRING_SIZE]; 302 db_expr_t addr, count; 303 boolean_t have_addr = FALSE; 304 int result; 305 306 t = db_read_token(); 307 if (t == tEOL) { --- 150 unchanged lines hidden (view full) --- 458 db_cmd_loop_done = 0; 459 while (!db_cmd_loop_done) { 460 if (db_print_position() != 0) 461 db_printf("\n"); 462 463 db_printf("db> "); 464 (void) db_read_line(); 465 | 333 int t; 334 char modif[TOK_STRING_SIZE]; 335 db_expr_t addr, count; 336 boolean_t have_addr = FALSE; 337 int result; 338 339 t = db_read_token(); 340 if (t == tEOL) { --- 150 unchanged lines hidden (view full) --- 491 db_cmd_loop_done = 0; 492 while (!db_cmd_loop_done) { 493 if (db_print_position() != 0) 494 db_printf("\n"); 495 496 db_printf("db> "); 497 (void) db_read_line(); 498 |
466 db_command(&db_last_command, &db_command_table, /* dopager */ 1); | 499 db_command(&db_last_command, &db_cmd_table, /* dopager */ 1); |
467 } 468} 469 470/* 471 * Execute a command on behalf of a script. The caller is responsible for 472 * making sure that the command string is < DB_MAXLINE or it will be 473 * truncated. 474 * 475 * XXXRW: Runs by injecting faked input into DDB input stream; it would be 476 * nicer to use an alternative approach that didn't mess with the previous 477 * command buffer. 478 */ 479void 480db_command_script(const char *command) 481{ 482 db_prev = db_next = db_dot; 483 db_inject_line(command); | 500 } 501} 502 503/* 504 * Execute a command on behalf of a script. The caller is responsible for 505 * making sure that the command string is < DB_MAXLINE or it will be 506 * truncated. 507 * 508 * XXXRW: Runs by injecting faked input into DDB input stream; it would be 509 * nicer to use an alternative approach that didn't mess with the previous 510 * command buffer. 511 */ 512void 513db_command_script(const char *command) 514{ 515 db_prev = db_next = db_dot; 516 db_inject_line(command); |
484 db_command(&db_last_command, &db_command_table, /* dopager */ 0); | 517 db_command(&db_last_command, &db_cmd_table, /* dopager */ 0); |
485} 486 487void 488db_error(s) 489 const char *s; 490{ 491 if (s) 492 db_printf("%s", s); --- 249 unchanged lines hidden --- | 518} 519 520void 521db_error(s) 522 const char *s; 523{ 524 if (s) 525 db_printf("%s", s); --- 249 unchanged lines hidden --- |