Deleted Added
full compact
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 ---