db_command.c revision 1.95.4.5 1 1.95.4.5 ad /* $NetBSD: db_command.c,v 1.95.4.5 2007/10/23 20:17:05 ad Exp $ */
2 1.64 simonb /*
3 1.1 cgd * Mach Operating System
4 1.1 cgd * Copyright (c) 1991,1990 Carnegie Mellon University
5 1.1 cgd * All Rights Reserved.
6 1.64 simonb *
7 1.1 cgd * Permission to use, copy, modify and distribute this software and its
8 1.1 cgd * documentation is hereby granted, provided that both the copyright
9 1.1 cgd * notice and this permission notice appear in all copies of the
10 1.1 cgd * software, derivative works or modified versions, and any portions
11 1.1 cgd * thereof, and that both notices appear in supporting documentation.
12 1.64 simonb *
13 1.30 pk * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
14 1.1 cgd * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
15 1.1 cgd * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 1.64 simonb *
17 1.1 cgd * Carnegie Mellon requests users of this software to return to
18 1.64 simonb *
19 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
20 1.1 cgd * School of Computer Science
21 1.1 cgd * Carnegie Mellon University
22 1.1 cgd * Pittsburgh PA 15213-3890
23 1.64 simonb *
24 1.1 cgd * any improvements or extensions that they make and grant Carnegie the
25 1.1 cgd * rights to redistribute these changes.
26 1.1 cgd */
27 1.95.4.2 ad /*
28 1.95.4.2 ad * Copyright (c) 1996, 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
29 1.95.4.2 ad * All rights reserved.
30 1.95.4.2 ad *
31 1.95.4.2 ad * This code is derived from software contributed to The NetBSD Foundation
32 1.95.4.2 ad * by Adam Hamsik.
33 1.95.4.2 ad *
34 1.95.4.2 ad * Redistribution and use in source and binary forms, with or without
35 1.95.4.2 ad * modification, are permitted provided that the following conditions
36 1.95.4.2 ad * are met:
37 1.95.4.2 ad * 1. Redistributions of source code must retain the above copyright
38 1.95.4.2 ad * notice, this list of conditions and the following disclaimer.
39 1.95.4.2 ad * 2. Redistributions in binary form must reproduce the above copyright
40 1.95.4.2 ad * notice, this list of conditions and the following disclaimer in the
41 1.95.4.2 ad * documentation and/or other materials provided with the distribution.
42 1.95.4.2 ad * 3. All advertising materials mentioning features or use of this software
43 1.95.4.2 ad * must display the following acknowledgement:
44 1.95.4.2 ad * This product includes software developed by the NetBSD
45 1.95.4.2 ad * Foundation, Inc. and its contributors.
46 1.95.4.2 ad * 4. Neither the name of The NetBSD Foundation nor the names of its
47 1.95.4.2 ad * contributors may be used to endorse or promote products derived
48 1.95.4.2 ad * from this software without specific prior written permission.
49 1.95.4.2 ad *
50 1.95.4.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 1.95.4.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 1.95.4.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 1.95.4.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 1.95.4.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 1.95.4.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 1.95.4.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 1.95.4.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 1.95.4.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 1.95.4.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 1.95.4.2 ad * POSSIBILITY OF SUCH DAMAGE.
61 1.95.4.2 ad */
62 1.25 mrg
63 1.63 lukem /*
64 1.63 lukem * Command dispatcher.
65 1.63 lukem */
66 1.63 lukem
67 1.63 lukem #include <sys/cdefs.h>
68 1.95.4.5 ad __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.95.4.5 2007/10/23 20:17:05 ad Exp $");
69 1.63 lukem
70 1.27 tron #include "opt_ddb.h"
71 1.69 briggs #include "opt_kgdb.h"
72 1.40 jhawk #include "opt_inet.h"
73 1.80 yamt #include "opt_ddbparam.h"
74 1.5 mycroft
75 1.7 mycroft #include <sys/param.h>
76 1.18 christos #include <sys/systm.h>
77 1.23 scottr #include <sys/reboot.h>
78 1.65 simonb #include <sys/device.h>
79 1.65 simonb #include <sys/malloc.h>
80 1.83 yamt #include <sys/mbuf.h>
81 1.65 simonb #include <sys/namei.h>
82 1.65 simonb #include <sys/pool.h>
83 1.7 mycroft #include <sys/proc.h>
84 1.36 chs #include <sys/vnode.h>
85 1.92 ad #include <sys/lockdebug.h>
86 1.92 ad #include <sys/sleepq.h>
87 1.95.4.5 ad #include <sys/cpu.h>
88 1.15 gwr
89 1.95.4.2 ad /*include queue macros*/
90 1.95.4.2 ad #include <sys/queue.h>
91 1.95.4.2 ad
92 1.1 cgd #include <machine/db_machdep.h> /* type definitions */
93 1.1 cgd
94 1.58 mrg #if defined(_KERNEL_OPT)
95 1.34 sommerfe #include "opt_multiprocessor.h"
96 1.34 sommerfe #endif
97 1.34 sommerfe
98 1.1 cgd #include <ddb/db_lex.h>
99 1.1 cgd #include <ddb/db_output.h>
100 1.10 pk #include <ddb/db_command.h>
101 1.16 christos #include <ddb/db_break.h>
102 1.16 christos #include <ddb/db_watch.h>
103 1.16 christos #include <ddb/db_run.h>
104 1.16 christos #include <ddb/db_variables.h>
105 1.16 christos #include <ddb/db_interface.h>
106 1.16 christos #include <ddb/db_sym.h>
107 1.16 christos #include <ddb/db_extern.h>
108 1.1 cgd
109 1.24 mrg #include <uvm/uvm_extern.h>
110 1.26 jonathan #include <uvm/uvm_ddb.h>
111 1.24 mrg
112 1.46 jhawk #include "arp.h"
113 1.46 jhawk
114 1.1 cgd /*
115 1.64 simonb * Results of command search.
116 1.64 simonb */
117 1.64 simonb #define CMD_UNIQUE 0
118 1.64 simonb #define CMD_FOUND 1
119 1.64 simonb #define CMD_NONE 2
120 1.64 simonb #define CMD_AMBIGUOUS 3
121 1.64 simonb
122 1.64 simonb /*
123 1.1 cgd * Exported global variables
124 1.1 cgd */
125 1.93 thorpej bool db_cmd_loop_done;
126 1.17 gwr label_t *db_recover;
127 1.64 simonb db_addr_t db_dot;
128 1.64 simonb db_addr_t db_last_addr;
129 1.64 simonb db_addr_t db_prev;
130 1.64 simonb db_addr_t db_next;
131 1.1 cgd
132 1.95.4.2 ad
133 1.95.4.2 ad /*
134 1.95.4.2 ad New DDB api for adding and removing commands uses three lists, because
135 1.95.4.2 ad we use two types of commands
136 1.95.4.2 ad a) standard commands without subcommands -> reboot
137 1.95.4.2 ad b) show commands which are subcommands of show command -> show aio_jobs
138 1.95.4.2 ad c) if defined machine specific commands
139 1.95.4.2 ad
140 1.95.4.2 ad ddb_add_cmd, ddb_rem_cmd use type (DDB_SHOW_CMD||DDB_BASE_CMD)argument to
141 1.95.4.2 ad add them to representativ lists.
142 1.95.4.2 ad */
143 1.95.4.2 ad
144 1.95.4.2 ad static const struct db_command db_command_table[];
145 1.95.4.2 ad static const struct db_command db_show_cmds[];
146 1.95.4.2 ad #ifdef DB_MACHINE_COMMANDS
147 1.95.4.2 ad static const struct db_command db_machine_command_table[];
148 1.95.4.2 ad #endif
149 1.95.4.2 ad
150 1.95.4.2 ad /* the global queue of all command tables */
151 1.95.4.2 ad TAILQ_HEAD(db_cmd_tbl_en_head, db_cmd_tbl_en);
152 1.95.4.2 ad
153 1.95.4.2 ad /* TAILQ entry used to register command tables */
154 1.95.4.2 ad struct db_cmd_tbl_en {
155 1.95.4.2 ad const struct db_command *db_cmd; /* cmd table */
156 1.95.4.2 ad TAILQ_ENTRY(db_cmd_tbl_en) db_cmd_next;
157 1.95.4.2 ad };
158 1.95.4.2 ad
159 1.95.4.2 ad /* head of base commands list */
160 1.95.4.2 ad static struct db_cmd_tbl_en_head db_base_cmd_list =
161 1.95.4.2 ad TAILQ_HEAD_INITIALIZER(db_base_cmd_list);
162 1.95.4.2 ad static struct db_cmd_tbl_en db_base_cmd_builtins =
163 1.95.4.2 ad { .db_cmd = db_command_table };
164 1.95.4.2 ad
165 1.95.4.2 ad /* head of show commands list */
166 1.95.4.2 ad static struct db_cmd_tbl_en_head db_show_cmd_list =
167 1.95.4.2 ad TAILQ_HEAD_INITIALIZER(db_show_cmd_list);
168 1.95.4.2 ad static struct db_cmd_tbl_en db_show_cmd_builtins =
169 1.95.4.2 ad { .db_cmd = db_show_cmds };
170 1.95.4.2 ad
171 1.95.4.2 ad /* head of machine commands list */
172 1.95.4.2 ad static struct db_cmd_tbl_en_head db_mach_cmd_list =
173 1.95.4.2 ad TAILQ_HEAD_INITIALIZER(db_mach_cmd_list);
174 1.95.4.2 ad #ifdef DB_MACHINE_COMMANDS
175 1.95.4.2 ad static struct db_cmd_tbl_en db_mach_cmd_builtins =
176 1.95.4.2 ad { .db_cmd = db_machine_command_table };
177 1.95.4.2 ad #endif
178 1.95.4.2 ad
179 1.1 cgd /*
180 1.1 cgd * if 'ed' style: 'dot' is set at start of last item printed,
181 1.1 cgd * and '+' points to next line.
182 1.1 cgd * Otherwise: 'dot' points to next item, '..' points to last.
183 1.1 cgd */
184 1.95 thorpej static bool db_ed_style = true;
185 1.64 simonb
186 1.95.4.2 ad static void db_init_commands(void);
187 1.95.4.2 ad static int db_register_tbl_entry(uint8_t type,
188 1.95.4.2 ad struct db_cmd_tbl_en *list_ent);
189 1.95.4.2 ad static void db_cmd_list(const struct db_cmd_tbl_en_head *);
190 1.64 simonb static int db_cmd_search(const char *, const struct db_command *,
191 1.95.4.2 ad const struct db_command **);
192 1.95.4.2 ad static void db_command(const struct db_command **);
193 1.95.4.2 ad static void db_buf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
194 1.94 matt static void db_event_print_cmd(db_expr_t, bool, db_expr_t, const char *);
195 1.94 matt static void db_fncall(db_expr_t, bool, db_expr_t, const char *);
196 1.95.4.2 ad static int db_get_list_type(const char *);
197 1.95.4.2 ad static void db_help_print_cmd(db_expr_t, bool, db_expr_t, const char *);
198 1.95.4.2 ad static void db_lock_print_cmd(db_expr_t, bool, db_expr_t, const char *);
199 1.95.4.2 ad static void db_mount_print_cmd(db_expr_t, bool, db_expr_t, const char *);
200 1.95.4.2 ad static void db_mbuf_print_cmd(db_expr_t, bool, db_expr_t, const char *);
201 1.94 matt static void db_malloc_print_cmd(db_expr_t, bool, db_expr_t, const char *);
202 1.94 matt static void db_map_print_cmd(db_expr_t, bool, db_expr_t, const char *);
203 1.95.4.2 ad static void db_namecache_print_cmd(db_expr_t, bool, db_expr_t,
204 1.95.4.2 ad const char *);
205 1.94 matt static void db_object_print_cmd(db_expr_t, bool, db_expr_t, const char *);
206 1.94 matt static void db_page_print_cmd(db_expr_t, bool, db_expr_t, const char *);
207 1.94 matt static void db_show_all_pages(db_expr_t, bool, db_expr_t, const char *);
208 1.94 matt static void db_pool_print_cmd(db_expr_t, bool, db_expr_t, const char *);
209 1.94 matt static void db_reboot_cmd(db_expr_t, bool, db_expr_t, const char *);
210 1.94 matt static void db_sifting_cmd(db_expr_t, bool, db_expr_t, const char *);
211 1.94 matt static void db_stack_trace_cmd(db_expr_t, bool, db_expr_t, const char *);
212 1.94 matt static void db_sync_cmd(db_expr_t, bool, db_expr_t, const char *);
213 1.94 matt static void db_uvmexp_print_cmd(db_expr_t, bool, db_expr_t, const char *);
214 1.94 matt static void db_vnode_print_cmd(db_expr_t, bool, db_expr_t, const char *);
215 1.64 simonb
216 1.64 simonb static const struct db_command db_show_cmds[] = {
217 1.95.4.2 ad /*added from all sub cmds*/
218 1.95.4.2 ad { DDB_ADD_CMD("callout", db_show_callout,
219 1.95.4.2 ad 0 ,"List all used callout functions.",NULL,NULL) },
220 1.95.4.2 ad { DDB_ADD_CMD("pages", db_show_all_pages,
221 1.95.4.2 ad 0 ,"List all used memory pages.",NULL,NULL) },
222 1.95.4.2 ad { DDB_ADD_CMD("procs", db_show_all_procs,
223 1.95.4.2 ad 0 ,"List all processes.",NULL,NULL) },
224 1.95.4.2 ad { DDB_ADD_CMD("pools", db_show_all_pools,
225 1.95.4.2 ad 0 ,"Show all poolS",NULL,NULL) },
226 1.95.4.2 ad /*added from all sub cmds*/
227 1.95.4.2 ad { DDB_ADD_CMD("aio_jobs", db_show_aio_jobs, 0,
228 1.95.4.2 ad "Show aio jobs",NULL,NULL) },
229 1.95.4.2 ad { DDB_ADD_CMD("all", NULL,
230 1.95.4.2 ad CS_COMPAT, NULL,NULL,NULL) },
231 1.64 simonb #if defined(INET) && (NARP > 0)
232 1.95.4.2 ad { DDB_ADD_CMD("arptab", db_show_arptab, 0,NULL,NULL,NULL) },
233 1.64 simonb #endif
234 1.95.4.2 ad { DDB_ADD_CMD("breaks", db_listbreak_cmd, 0,
235 1.95.4.2 ad "Display all breaks.",NULL,NULL) },
236 1.95.4.2 ad { DDB_ADD_CMD("buf", db_buf_print_cmd, 0,
237 1.95.4.2 ad "Print the struct buf at address.", "[/f] address",NULL) },
238 1.95.4.2 ad { DDB_ADD_CMD("event", db_event_print_cmd, 0,
239 1.95.4.2 ad "Print all the non-zero evcnt(9) event counters.", "[/f]",NULL) },
240 1.95.4.2 ad { DDB_ADD_CMD("lock", db_lock_print_cmd, 0,NULL,NULL,NULL) },
241 1.95.4.2 ad { DDB_ADD_CMD("malloc", db_malloc_print_cmd,0,NULL,NULL,NULL) },
242 1.95.4.2 ad { DDB_ADD_CMD("map", db_map_print_cmd, 0,
243 1.95.4.2 ad "Print the vm_map at address.", "[/f] address",NULL) },
244 1.95.4.2 ad { DDB_ADD_CMD("mount", db_mount_print_cmd, 0,
245 1.95.4.2 ad "Print the mount structure at address.", "[/f] address",NULL) },
246 1.95.4.2 ad { DDB_ADD_CMD("mbuf", db_mbuf_print_cmd, 0,NULL,NULL,
247 1.95.4.2 ad "-c prints all mbuf chains") },
248 1.95.4.2 ad { DDB_ADD_CMD("ncache", db_namecache_print_cmd, 0,
249 1.95.4.2 ad "Dump the namecache list.", "address",NULL) },
250 1.95.4.2 ad { DDB_ADD_CMD("object", db_object_print_cmd, 0,
251 1.95.4.2 ad "Print the vm_object at address.", "[/f] address",NULL) },
252 1.95.4.2 ad { DDB_ADD_CMD("page", db_page_print_cmd, 0,
253 1.95.4.2 ad "Print the vm_page at address.", "[/f] address",NULL) },
254 1.95.4.2 ad { DDB_ADD_CMD("pool", db_pool_print_cmd, 0,
255 1.95.4.2 ad "Print the pool at address.", "[/clp] address",NULL) },
256 1.95.4.2 ad { DDB_ADD_CMD("registers", db_show_regs, 0,
257 1.95.4.2 ad "Display the register set.", "[/u]",NULL) },
258 1.95.4.2 ad { DDB_ADD_CMD("sched_qs", db_show_sched_qs, 0,
259 1.95.4.2 ad "Print the state of the scheduler's run queues.",
260 1.95.4.2 ad NULL,NULL) },
261 1.95.4.2 ad { DDB_ADD_CMD("uvmexp", db_uvmexp_print_cmd, 0,
262 1.95.4.2 ad "Print a selection of UVM counters and statistics.",
263 1.95.4.2 ad NULL,NULL) },
264 1.95.4.2 ad { DDB_ADD_CMD("vnode", db_vnode_print_cmd, 0,
265 1.95.4.2 ad "Print the vnode at address.", "[/f] address",NULL) },
266 1.95.4.2 ad { DDB_ADD_CMD("watches", db_listwatch_cmd, 0,
267 1.95.4.2 ad "Display all watchpoints.", NULL,NULL) },
268 1.95.4.2 ad { DDB_ADD_CMD(NULL, NULL, 0,NULL,NULL,NULL) }
269 1.64 simonb };
270 1.64 simonb
271 1.77 yamt /* arch/<arch>/<arch>/db_interface.c */
272 1.77 yamt #ifdef DB_MACHINE_COMMANDS
273 1.77 yamt extern const struct db_command db_machine_command_table[];
274 1.77 yamt #endif
275 1.77 yamt
276 1.64 simonb static const struct db_command db_command_table[] = {
277 1.95.4.2 ad { DDB_ADD_CMD("b", db_breakpoint_cmd, 0,
278 1.95.4.2 ad "Set a breakpoint at address", "[/u] address[,count].",NULL) },
279 1.95.4.2 ad { DDB_ADD_CMD("break", db_breakpoint_cmd, 0,
280 1.95.4.2 ad "Set a breakpoint at address", "[/u] address[,count].",NULL) },
281 1.95.4.2 ad { DDB_ADD_CMD("bt", db_stack_trace_cmd, 0,
282 1.95.4.2 ad "Show backtrace.", "See help trace.",NULL) },
283 1.95.4.2 ad { DDB_ADD_CMD("c", db_continue_cmd, 0,
284 1.95.4.2 ad "Continue execution.", "[/c]",NULL) },
285 1.95.4.2 ad { DDB_ADD_CMD("call", db_fncall, CS_OWN,
286 1.95.4.2 ad "Call the function", "address[(expression[,...])]",NULL) },
287 1.95.4.2 ad { DDB_ADD_CMD("callout", db_show_callout, 0, NULL,
288 1.95.4.2 ad NULL,NULL ) },
289 1.95.4.2 ad { DDB_ADD_CMD("continue", db_continue_cmd, 0,
290 1.95.4.2 ad "Continue execution.", "[/c]",NULL) },
291 1.95.4.2 ad { DDB_ADD_CMD("d", db_delete_cmd, 0,
292 1.95.4.2 ad "Delete a breakpoint.", "address | #number",NULL) },
293 1.95.4.2 ad { DDB_ADD_CMD("delete", db_delete_cmd, 0,
294 1.95.4.2 ad "Delete a breakpoint.", "address | #number",NULL) },
295 1.95.4.2 ad { DDB_ADD_CMD("dmesg", db_dmesg, 0,
296 1.95.4.2 ad "Show kernel message buffer.", "[count]",NULL) },
297 1.95.4.2 ad { DDB_ADD_CMD("dwatch", db_deletewatch_cmd, 0,
298 1.95.4.2 ad "Delete the watchpoint.", "address",NULL) },
299 1.95.4.2 ad { DDB_ADD_CMD("examine", db_examine_cmd, CS_SET_DOT,
300 1.95.4.2 ad "Display the address locations.",
301 1.95.4.2 ad "[/modifier] address[,count]",NULL) },
302 1.95.4.2 ad { DDB_ADD_CMD("help", db_help_print_cmd, CS_OWN|CS_NOREPEAT,
303 1.95.4.2 ad "Display help about commands",
304 1.95.4.2 ad "Use other commands as arguments.",NULL) },
305 1.95.4.2 ad { DDB_ADD_CMD("kill", db_kill_proc, CS_OWN,
306 1.95.4.2 ad "Send a signal to the process","pid[,signal_number]",
307 1.95.4.2 ad " pid:\t\t\tthe process id (may need 0t prefix for decimal)\n"
308 1.95.4.2 ad " signal_number:\tthe signal to send") },
309 1.69 briggs #ifdef KGDB
310 1.95.4.2 ad { DDB_ADD_CMD("kgdb", db_kgdb_cmd, 0, NULL,NULL,NULL) },
311 1.64 simonb #endif
312 1.95.4.2 ad { DDB_ADD_CMD("machine",NULL,CS_MACH,
313 1.95.4.2 ad "Architecture specific functions.",NULL,NULL) },
314 1.95.4.2 ad { DDB_ADD_CMD("match", db_trace_until_matching_cmd,0,
315 1.95.4.2 ad "Stop at the matching return instruction.","See help next",NULL) },
316 1.95.4.2 ad { DDB_ADD_CMD("next", db_trace_until_matching_cmd,0,
317 1.95.4.2 ad "Stop at the matching return instruction.","[/p]",NULL) },
318 1.95.4.2 ad { DDB_ADD_CMD("p", db_print_cmd, 0,
319 1.95.4.2 ad "Print address according to the format.",
320 1.95.4.2 ad "[/axzodurc] address [address ...]",NULL) },
321 1.95.4.2 ad { DDB_ADD_CMD("print", db_print_cmd, 0,
322 1.95.4.2 ad "Print address according to the format.",
323 1.95.4.2 ad "[/axzodurc] address [address ...]",NULL) },
324 1.95.4.2 ad { DDB_ADD_CMD("ps", db_show_all_procs, 0,
325 1.95.4.2 ad "Print all processes.","See show all procs",NULL) },
326 1.95.4.2 ad { DDB_ADD_CMD("reboot", db_reboot_cmd, CS_OWN,
327 1.95.4.2 ad "Reboot","0x1 RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
328 1.95.4.2 ad "0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN",NULL) },
329 1.95.4.2 ad { DDB_ADD_CMD("s", db_single_step_cmd, 0,
330 1.95.4.2 ad "Single-step count times.","[/p] [,count]",NULL) },
331 1.95.4.2 ad { DDB_ADD_CMD("search", db_search_cmd, CS_OWN|CS_SET_DOT,
332 1.95.4.2 ad "Search memory from address for value.",
333 1.95.4.2 ad "[/bhl] address value [mask] [,count]",NULL) },
334 1.95.4.2 ad { DDB_ADD_CMD("set", db_set_cmd, CS_OWN,
335 1.95.4.2 ad "Set the named variable","$variable [=] expression",NULL) },
336 1.95.4.3 ad { DDB_ADD_CMD("show", NULL, CS_SHOW,
337 1.95.4.2 ad "Show kernel stats.", NULL,NULL) },
338 1.95.4.2 ad { DDB_ADD_CMD("sifting", db_sifting_cmd, CS_OWN,
339 1.95.4.2 ad "Search the symbol tables ","[/F] string",NULL) },
340 1.95.4.2 ad { DDB_ADD_CMD("step", db_single_step_cmd, 0,
341 1.95.4.2 ad "Single-step count times.","[/p] [,count]",NULL) },
342 1.95.4.2 ad { DDB_ADD_CMD("sync", db_sync_cmd, CS_OWN,
343 1.95.4.2 ad "Force a crash dump, and then reboot.",NULL,NULL) },
344 1.95.4.2 ad { DDB_ADD_CMD("trace", db_stack_trace_cmd, 0,
345 1.95.4.2 ad "Stack trace from frame-address.",
346 1.95.4.2 ad "[/u[l]] [frame-address][,count]",NULL) },
347 1.95.4.2 ad { DDB_ADD_CMD("until", db_trace_until_call_cmd,0,
348 1.95.4.2 ad "Stop at the next call or return instruction.","[/p]",NULL) },
349 1.95.4.2 ad { DDB_ADD_CMD("w", db_write_cmd, CS_MORE|CS_SET_DOT,
350 1.95.4.2 ad "Set a watchpoint for a region. ","address[,size]",NULL) },
351 1.95.4.2 ad { DDB_ADD_CMD("watch", db_watchpoint_cmd, CS_MORE,
352 1.95.4.2 ad "Set a watchpoint for a region. ","address[,size]",NULL) },
353 1.95.4.2 ad { DDB_ADD_CMD("write", db_write_cmd, CS_MORE|CS_SET_DOT,
354 1.95.4.2 ad "Write the expressions at succeeding locations.",
355 1.95.4.2 ad "[/bhl] address expression [expression ...]",NULL) },
356 1.95.4.2 ad { DDB_ADD_CMD("x", db_examine_cmd, CS_SET_DOT,
357 1.95.4.2 ad "Display the address locations.",
358 1.95.4.2 ad "[/modifier] address[,count]",NULL) },
359 1.95.4.2 ad { DDB_ADD_CMD(NULL, NULL, 0, NULL, NULL, NULL) }
360 1.64 simonb };
361 1.64 simonb
362 1.64 simonb static const struct db_command *db_last_command = NULL;
363 1.80 yamt #if defined(DDB_COMMANDONENTER)
364 1.81 yamt char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
365 1.81 yamt #else /* defined(DDB_COMMANDONENTER) */
366 1.81 yamt char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
367 1.80 yamt #endif /* defined(DDB_COMMANDONENTER) */
368 1.80 yamt #define DB_LINE_SEP ';'
369 1.1 cgd
370 1.1 cgd /*
371 1.1 cgd * Utility routine - discard tokens through end-of-line.
372 1.1 cgd */
373 1.1 cgd void
374 1.64 simonb db_skip_to_eol(void)
375 1.1 cgd {
376 1.64 simonb int t;
377 1.64 simonb
378 1.1 cgd do {
379 1.64 simonb t = db_read_token();
380 1.1 cgd } while (t != tEOL);
381 1.1 cgd }
382 1.1 cgd
383 1.64 simonb void
384 1.89 uwe db_error(const char *s)
385 1.64 simonb {
386 1.64 simonb
387 1.64 simonb if (s)
388 1.64 simonb db_printf("%s", s);
389 1.64 simonb db_flush_lex();
390 1.64 simonb longjmp(db_recover);
391 1.64 simonb }
392 1.64 simonb
393 1.95.4.2 ad /*Execute commandlist after ddb start
394 1.95.4.2 ad *This function goes through the command list created from commands and ';'
395 1.95.4.2 ad */
396 1.95.4.2 ad
397 1.81 yamt static void
398 1.81 yamt db_execute_commandlist(const char *cmdlist)
399 1.81 yamt {
400 1.81 yamt const char *cmd = cmdlist;
401 1.81 yamt const struct db_command *dummy = NULL;
402 1.81 yamt
403 1.81 yamt while (*cmd != '\0') {
404 1.81 yamt const char *ep = cmd;
405 1.81 yamt
406 1.81 yamt while (*ep != '\0' && *ep != DB_LINE_SEP) {
407 1.81 yamt ep++;
408 1.81 yamt }
409 1.81 yamt db_set_line(cmd, ep);
410 1.95.4.2 ad db_command(&dummy);
411 1.81 yamt cmd = ep;
412 1.81 yamt if (*cmd == DB_LINE_SEP) {
413 1.81 yamt cmd++;
414 1.81 yamt }
415 1.81 yamt }
416 1.81 yamt }
417 1.81 yamt
418 1.95.4.2 ad /*Initialize ddb command tables*/
419 1.95.4.2 ad void
420 1.95.4.2 ad db_init_commands(void)
421 1.95.4.2 ad {
422 1.95.4.2 ad static bool done = false;
423 1.95.4.2 ad
424 1.95.4.2 ad if (done) return;
425 1.95.4.2 ad done = true;
426 1.95.4.2 ad
427 1.95.4.2 ad /* register command tables */
428 1.95.4.2 ad (void)db_register_tbl_entry(DDB_BASE_CMD, &db_base_cmd_builtins);
429 1.95.4.2 ad #ifdef DB_MACHINE_COMMANDS
430 1.95.4.2 ad (void)db_register_tbl_entry(DDB_MACH_CMD, &db_mach_cmd_builtins);
431 1.95.4.2 ad #endif
432 1.95.4.2 ad (void)db_register_tbl_entry(DDB_SHOW_CMD, &db_show_cmd_builtins);
433 1.95.4.2 ad }
434 1.95.4.2 ad
435 1.95.4.2 ad
436 1.95.4.2 ad /*
437 1.95.4.2 ad * Add command table to the specified list
438 1.95.4.2 ad * Arg:
439 1.95.4.2 ad * int type specifies type of command table DDB_SHOW_CMD|DDB_BASE_CMD|DDB_MAC_CMD
440 1.95.4.2 ad * *cmd_tbl poiter to static allocated db_command table
441 1.95.4.2 ad *
442 1.95.4.2 ad *Command table must be NULL terminated array of struct db_command
443 1.95.4.2 ad */
444 1.95.4.2 ad int
445 1.95.4.2 ad db_register_tbl(uint8_t type, const struct db_command *cmd_tbl)
446 1.95.4.2 ad {
447 1.95.4.2 ad struct db_cmd_tbl_en *list_ent;
448 1.95.4.2 ad
449 1.95.4.2 ad if (cmd_tbl->name == 0)
450 1.95.4.2 ad /* empty list - ignore */
451 1.95.4.2 ad return 0;
452 1.95.4.2 ad
453 1.95.4.2 ad /* force builtin commands to be registered first */
454 1.95.4.2 ad db_init_commands();
455 1.95.4.2 ad
456 1.95.4.2 ad /* now create a list entry for this table */
457 1.95.4.2 ad list_ent = malloc(sizeof(struct db_cmd_tbl_en), M_TEMP, M_ZERO);
458 1.95.4.2 ad if (list_ent == NULL)
459 1.95.4.2 ad return ENOMEM;
460 1.95.4.2 ad list_ent->db_cmd=cmd_tbl;
461 1.95.4.2 ad
462 1.95.4.2 ad /* and register it */
463 1.95.4.2 ad return db_register_tbl_entry(type, list_ent);
464 1.95.4.2 ad }
465 1.95.4.2 ad
466 1.95.4.2 ad static int
467 1.95.4.2 ad db_register_tbl_entry(uint8_t type, struct db_cmd_tbl_en *list_ent)
468 1.95.4.2 ad {
469 1.95.4.2 ad struct db_cmd_tbl_en_head *list;
470 1.95.4.2 ad
471 1.95.4.2 ad switch(type) {
472 1.95.4.2 ad case DDB_BASE_CMD:
473 1.95.4.2 ad list = &db_base_cmd_list;
474 1.95.4.2 ad break;
475 1.95.4.2 ad case DDB_SHOW_CMD:
476 1.95.4.2 ad list = &db_show_cmd_list;
477 1.95.4.2 ad break;
478 1.95.4.2 ad case DDB_MACH_CMD:
479 1.95.4.2 ad list = &db_mach_cmd_list;
480 1.95.4.2 ad break;
481 1.95.4.2 ad default:
482 1.95.4.2 ad return ENOENT;
483 1.95.4.2 ad }
484 1.95.4.2 ad
485 1.95.4.2 ad TAILQ_INSERT_TAIL(list, list_ent, db_cmd_next);
486 1.95.4.2 ad
487 1.95.4.2 ad return 0;
488 1.95.4.2 ad }
489 1.95.4.2 ad
490 1.95.4.2 ad /*
491 1.95.4.2 ad * Remove command table specified with db_cmd address == cmd_tbl
492 1.95.4.2 ad */
493 1.95.4.2 ad int
494 1.95.4.2 ad db_unregister_tbl(uint8_t type,const struct db_command *cmd_tbl)
495 1.95.4.2 ad {
496 1.95.4.2 ad struct db_cmd_tbl_en *list_ent;
497 1.95.4.2 ad struct db_cmd_tbl_en_head *list;
498 1.95.4.2 ad
499 1.95.4.2 ad /* find list on which the entry should live */
500 1.95.4.2 ad switch (type) {
501 1.95.4.2 ad case DDB_BASE_CMD:
502 1.95.4.2 ad list=&db_base_cmd_list;
503 1.95.4.2 ad break;
504 1.95.4.2 ad case DDB_SHOW_CMD:
505 1.95.4.2 ad list=&db_show_cmd_list;
506 1.95.4.2 ad break;
507 1.95.4.2 ad case DDB_MACH_CMD:
508 1.95.4.2 ad list=&db_mach_cmd_list;
509 1.95.4.2 ad break;
510 1.95.4.2 ad default:
511 1.95.4.2 ad return EINVAL;
512 1.95.4.2 ad }
513 1.95.4.2 ad
514 1.95.4.2 ad TAILQ_FOREACH (list_ent,list,db_cmd_next) {
515 1.95.4.2 ad if (list_ent->db_cmd == cmd_tbl){
516 1.95.4.2 ad TAILQ_REMOVE(list,
517 1.95.4.2 ad list_ent,db_cmd_next);
518 1.95.4.2 ad free(list_ent,M_TEMP);
519 1.95.4.2 ad return 0;
520 1.95.4.2 ad }
521 1.95.4.2 ad }
522 1.95.4.2 ad return ENOENT;
523 1.95.4.2 ad }
524 1.95.4.2 ad
525 1.95.4.2 ad /*This function is called from machine trap code.*/
526 1.64 simonb void
527 1.64 simonb db_command_loop(void)
528 1.64 simonb {
529 1.95.4.2 ad
530 1.64 simonb label_t db_jmpbuf;
531 1.64 simonb label_t *savejmp;
532 1.64 simonb
533 1.64 simonb /*
534 1.64 simonb * Initialize 'prev' and 'next' to dot.
535 1.64 simonb */
536 1.64 simonb db_prev = db_dot;
537 1.64 simonb db_next = db_dot;
538 1.64 simonb
539 1.95.4.2 ad db_cmd_loop_done = false;
540 1.64 simonb
541 1.95.4.2 ad /*Init default command tables add machine, base,
542 1.95.4.2 ad show command tables to the list*/
543 1.95.4.2 ad db_init_commands();
544 1.95.4.2 ad
545 1.95.4.2 ad /*save context for return from ddb*/
546 1.64 simonb savejmp = db_recover;
547 1.64 simonb db_recover = &db_jmpbuf;
548 1.64 simonb (void) setjmp(&db_jmpbuf);
549 1.64 simonb
550 1.95.4.2 ad /*Execute default ddb start commands*/
551 1.81 yamt db_execute_commandlist(db_cmd_on_enter);
552 1.80 yamt
553 1.95.4.2 ad (void) setjmp(&db_jmpbuf);
554 1.64 simonb while (!db_cmd_loop_done) {
555 1.64 simonb if (db_print_position() != 0)
556 1.64 simonb db_printf("\n");
557 1.64 simonb db_output_line = 0;
558 1.64 simonb
559 1.64 simonb
560 1.64 simonb #ifdef MULTIPROCESSOR
561 1.64 simonb db_printf("db{%ld}> ", (long)cpu_number());
562 1.64 simonb #else
563 1.64 simonb db_printf("db> ");
564 1.64 simonb #endif
565 1.64 simonb (void) db_read_line();
566 1.64 simonb
567 1.95.4.2 ad db_command(&db_last_command);
568 1.64 simonb }
569 1.64 simonb
570 1.64 simonb db_recover = savejmp;
571 1.64 simonb }
572 1.1 cgd
573 1.1 cgd /*
574 1.95.4.2 ad * Search for command table for command prefix
575 1.95.4.4 ad * ret: CMD_UNIQUE -> completely matches command
576 1.95.4.4 ad * CMD_FOUND -> matches prefix of single command
577 1.95.4.4 ad * CMD_AMBIGIOUS -> matches prefix of more than one command
578 1.95.4.4 ad * CMD_NONE -> command not found
579 1.1 cgd */
580 1.64 simonb static int
581 1.95.4.2 ad db_cmd_search(const char *name,const struct db_command *table,
582 1.64 simonb const struct db_command **cmdp)
583 1.1 cgd {
584 1.95.4.2 ad
585 1.53 jdolecek const struct db_command *cmd;
586 1.95.4.4 ad int result;
587 1.1 cgd
588 1.95.4.4 ad result = CMD_NONE;
589 1.1 cgd for (cmd = table; cmd->name != 0; cmd++) {
590 1.64 simonb const char *lp;
591 1.64 simonb const char *rp;
592 1.64 simonb
593 1.64 simonb lp = name;
594 1.64 simonb rp = cmd->name;
595 1.95.4.4 ad while (*lp != '\0' && *lp == *rp) {
596 1.64 simonb rp++;
597 1.95.4.3 ad lp++;
598 1.95.4.3 ad }
599 1.95.4.4 ad
600 1.95.4.4 ad if (*lp != '\0') /* mismatch or extra chars in name */
601 1.95.4.4 ad continue;
602 1.95.4.4 ad
603 1.95.4.4 ad if (*rp == '\0') { /* complete match */
604 1.95.4.3 ad *cmdp = cmd;
605 1.95.4.3 ad return (CMD_UNIQUE);
606 1.64 simonb }
607 1.95.4.4 ad
608 1.95.4.4 ad /* prefix match: end of name, not end of command */
609 1.95.4.4 ad if (result == CMD_NONE) {
610 1.95.4.4 ad result = CMD_FOUND;
611 1.95.4.4 ad *cmdp = cmd;
612 1.95.4.4 ad }
613 1.95.4.4 ad else if (result == CMD_FOUND) {
614 1.95.4.4 ad result = CMD_AMBIGUOUS;
615 1.95.4.4 ad *cmdp = NULL;
616 1.1 cgd }
617 1.1 cgd }
618 1.95.4.4 ad
619 1.1 cgd return (result);
620 1.1 cgd }
621 1.1 cgd
622 1.95.4.2 ad /*
623 1.95.4.2 ad *List commands to the console.
624 1.95.4.2 ad */
625 1.64 simonb static void
626 1.95.4.2 ad db_cmd_list(const struct db_cmd_tbl_en_head *list)
627 1.1 cgd {
628 1.95.4.2 ad
629 1.95.4.2 ad struct db_cmd_tbl_en *list_ent;
630 1.95.4.2 ad const struct db_command *table;
631 1.95.4.2 ad size_t i, j, w, columns, lines, numcmds, width=0;
632 1.53 jdolecek const char *p;
633 1.1 cgd
634 1.95.4.2 ad TAILQ_FOREACH(list_ent,list,db_cmd_next) {
635 1.95.4.2 ad table = list_ent->db_cmd;
636 1.95.4.2 ad for (i = 0; table[i].name != NULL; i++) {
637 1.95.4.2 ad w = strlen(table[i].name);
638 1.95.4.2 ad if (w > width)
639 1.95.4.2 ad width = w;
640 1.95.4.2 ad }
641 1.32 lukem }
642 1.95.4.2 ad
643 1.32 lukem width = DB_NEXT_TAB(width);
644 1.32 lukem
645 1.32 lukem columns = db_max_width / width;
646 1.32 lukem if (columns == 0)
647 1.32 lukem columns = 1;
648 1.95.4.2 ad
649 1.95.4.2 ad TAILQ_FOREACH(list_ent,list,db_cmd_next) {
650 1.95.4.2 ad table = list_ent->db_cmd;
651 1.95.4.2 ad
652 1.95.4.2 ad for (numcmds = 0; table[numcmds].name != NULL; numcmds++)
653 1.95.4.2 ad ;
654 1.95.4.2 ad lines = (numcmds + columns - 1) / columns;
655 1.95.4.2 ad
656 1.95.4.2 ad for (i = 0; i < lines; i++) {
657 1.95.4.2 ad for (j = 0; j < columns; j++) {
658 1.95.4.2 ad p = table[j * lines + i].name;
659 1.95.4.2 ad if (p)
660 1.95.4.2 ad db_printf("%s", p);
661 1.95.4.2 ad if (j * lines + i + lines >= numcmds) {
662 1.95.4.2 ad db_putchar('\n');
663 1.95.4.2 ad break;
664 1.95.4.2 ad }
665 1.95.4.2 ad if (p) {
666 1.95.4.2 ad w = strlen(p);
667 1.95.4.2 ad while (w < width) {
668 1.95.4.2 ad w = DB_NEXT_TAB(w);
669 1.95.4.2 ad db_putchar('\t');
670 1.95.4.2 ad }
671 1.95.4.2 ad }
672 1.95.4.2 ad }
673 1.95.4.2 ad }
674 1.95.4.2 ad }
675 1.95.4.2 ad return;
676 1.95.4.2 ad }
677 1.95.4.2 ad
678 1.95.4.2 ad /*
679 1.95.4.2 ad *Returns type of list for command with name *name.
680 1.95.4.2 ad */
681 1.95.4.2 ad static int
682 1.95.4.2 ad db_get_list_type(const char *name)
683 1.95.4.2 ad {
684 1.95.4.2 ad
685 1.95.4.2 ad const struct db_command *cmd;
686 1.95.4.2 ad struct db_cmd_tbl_en *list_ent;
687 1.95.4.2 ad int error,ret=-1;
688 1.95.4.2 ad
689 1.95.4.2 ad /* search for the command name */
690 1.95.4.2 ad TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next) {
691 1.95.4.2 ad /*
692 1.95.4.2 ad * cmd_search returns CMD_UNIQUE, CMD_FOUND ...
693 1.95.4.2 ad * CMD_UNIQUE when name was completly matched to cmd->name
694 1.95.4.2 ad * CMD_FOUND when name was only partially matched to cmd->name
695 1.95.4.2 ad * CMD_NONE command not found in a list
696 1.95.4.2 ad * CMD_AMBIGIOUS ->more partialy matches
697 1.95.4.2 ad */
698 1.95.4.2 ad
699 1.95.4.2 ad error = db_cmd_search(name, list_ent->db_cmd, &cmd);
700 1.95.4.2 ad
701 1.95.4.2 ad if (error == CMD_UNIQUE) {
702 1.95.4.2 ad /* exact match found */
703 1.95.4.2 ad if (cmd->flag == CS_SHOW) {
704 1.95.4.2 ad ret = DDB_SHOW_CMD;
705 1.32 lukem break;
706 1.32 lukem }
707 1.95.4.2 ad if (cmd->flag == CS_MACH) {
708 1.95.4.2 ad ret = DDB_MACH_CMD;
709 1.95.4.2 ad break;
710 1.95.4.2 ad } else {
711 1.95.4.2 ad ret = DDB_BASE_CMD;
712 1.95.4.2 ad break;
713 1.32 lukem }
714 1.95.4.2 ad
715 1.95.4.2 ad } else if (error == CMD_FOUND){
716 1.95.4.2 ad /*
717 1.95.4.2 ad * partial match, search will continue, but
718 1.95.4.2 ad * note current result in case we won't
719 1.95.4.2 ad * find anything better.
720 1.95.4.2 ad */
721 1.95.4.2 ad if (cmd->flag == CS_SHOW)
722 1.95.4.2 ad ret = DDB_SHOW_CMD;
723 1.95.4.2 ad if (cmd->flag == CS_MACH)
724 1.95.4.2 ad ret = DDB_MACH_CMD;
725 1.95.4.2 ad else
726 1.95.4.2 ad ret = DDB_BASE_CMD;
727 1.32 lukem }
728 1.1 cgd }
729 1.95.4.2 ad
730 1.95.4.2 ad return ret;
731 1.1 cgd }
732 1.1 cgd
733 1.95.4.2 ad /*
734 1.95.4.2 ad *Parse command line and execute apropriate function.
735 1.95.4.2 ad */
736 1.64 simonb static void
737 1.95.4.2 ad db_command(const struct db_command **last_cmdp)
738 1.1 cgd {
739 1.95.4.2 ad const struct db_command *command;
740 1.95.4.2 ad struct db_cmd_tbl_en *list_ent;
741 1.95.4.2 ad struct db_cmd_tbl_en_head *list;
742 1.95.4.2 ad
743 1.1 cgd int t;
744 1.95.4.2 ad int result;
745 1.95.4.2 ad
746 1.1 cgd char modif[TOK_STRING_SIZE];
747 1.1 cgd db_expr_t addr, count;
748 1.95 thorpej bool have_addr = false;
749 1.1 cgd
750 1.95.4.2 ad static db_expr_t last_count = 0;
751 1.95.4.2 ad
752 1.95.4.2 ad command = NULL; /* XXX gcc */
753 1.86 mrg
754 1.1 cgd t = db_read_token();
755 1.38 jhawk if ((t == tEOL) || (t == tCOMMA)) {
756 1.1 cgd /*
757 1.64 simonb * An empty line repeats last command, at 'next'.
758 1.64 simonb * Only a count repeats the last command with the new count.
759 1.64 simonb */
760 1.95.4.2 ad command = *last_cmdp;
761 1.95.4.2 ad
762 1.95.4.2 ad if (!command)
763 1.95.4.2 ad return;
764 1.95.4.2 ad
765 1.64 simonb addr = (db_expr_t)db_next;
766 1.64 simonb if (t == tCOMMA) {
767 1.64 simonb if (!db_expression(&count)) {
768 1.64 simonb db_printf("Count missing\n");
769 1.64 simonb db_flush_lex();
770 1.64 simonb return;
771 1.64 simonb }
772 1.64 simonb } else
773 1.64 simonb count = last_count;
774 1.95 thorpej have_addr = false;
775 1.64 simonb modif[0] = '\0';
776 1.64 simonb db_skip_to_eol();
777 1.95.4.2 ad
778 1.64 simonb } else if (t == tEXCL) {
779 1.64 simonb db_fncall(0, 0, 0, NULL);
780 1.64 simonb return;
781 1.95.4.2 ad
782 1.64 simonb } else if (t != tIDENT) {
783 1.64 simonb db_printf("?\n");
784 1.64 simonb db_flush_lex();
785 1.64 simonb return;
786 1.95.4.2 ad
787 1.64 simonb } else {
788 1.95.4.2 ad
789 1.95.4.2 ad switch(db_get_list_type(db_tok_string)) {
790 1.95.4.2 ad
791 1.95.4.2 ad case DDB_BASE_CMD:
792 1.95.4.3 ad list = &db_base_cmd_list;
793 1.95.4.2 ad break;
794 1.95.4.3 ad
795 1.95.4.2 ad case DDB_SHOW_CMD:
796 1.95.4.3 ad list = &db_show_cmd_list;
797 1.95.4.2 ad /* need to read show subcommand if show command list
798 1.95.4.2 ad is used. */
799 1.95.4.3 ad t = db_read_token();
800 1.95.4.2 ad
801 1.95.4.2 ad if (t != tIDENT) {
802 1.95.4.2 ad /* if only show command is executed, print
803 1.95.4.2 ad all subcommands */
804 1.95.4.2 ad db_cmd_list(list);
805 1.64 simonb db_flush_lex();
806 1.64 simonb return;
807 1.95.4.2 ad }
808 1.95.4.2 ad break;
809 1.95.4.2 ad case DDB_MACH_CMD:
810 1.95.4.3 ad list = &db_mach_cmd_list;
811 1.95.4.2 ad /* need to read machine subcommand if
812 1.95.4.2 ad machine level 2 command list is used. */
813 1.95.4.2 ad t = db_read_token();
814 1.95.4.2 ad
815 1.95.4.2 ad if (t != tIDENT) {
816 1.95.4.2 ad /* if only show command is executed, print
817 1.95.4.2 ad all subcommands */
818 1.95.4.2 ad db_cmd_list(list);
819 1.64 simonb db_flush_lex();
820 1.64 simonb return;
821 1.95.4.2 ad }
822 1.95.4.2 ad break;
823 1.95.4.2 ad default:
824 1.95.4.2 ad db_printf("No such command\n");
825 1.95.4.2 ad db_flush_lex();
826 1.95.4.2 ad return;
827 1.95.4.2 ad }
828 1.95.4.2 ad
829 1.95.4.2 ad COMPAT_RET:
830 1.95.4.3 ad TAILQ_FOREACH(list_ent, list, db_cmd_next) {
831 1.95.4.2 ad result = db_cmd_search(db_tok_string, list_ent->db_cmd,
832 1.95.4.2 ad &command);
833 1.95.4.2 ad
834 1.95.4.2 ad /* after CMD_UNIQUE in cmd_list only a single command
835 1.95.4.2 ad name is possible */
836 1.95.4.2 ad if (result == CMD_UNIQUE)
837 1.64 simonb break;
838 1.95.4.2 ad
839 1.95.4.2 ad }
840 1.95.4.2 ad
841 1.95.4.3 ad /* check compatibility flag */
842 1.95.4.2 ad if (command && command->flag & CS_COMPAT){
843 1.95.4.2 ad t = db_read_token();
844 1.95.4.2 ad if (t != tIDENT) {
845 1.95.4.2 ad db_cmd_list(list);
846 1.64 simonb db_flush_lex();
847 1.64 simonb return;
848 1.64 simonb }
849 1.95.4.2 ad
850 1.95.4.2 ad /* support only level 2 commands here */
851 1.95.4.2 ad goto COMPAT_RET;
852 1.95.4.2 ad }
853 1.95.4.2 ad
854 1.95.4.2 ad if (!command) {
855 1.95.4.2 ad db_printf("No such command\n");
856 1.95.4.2 ad db_flush_lex();
857 1.95.4.2 ad return;
858 1.1 cgd }
859 1.1 cgd
860 1.95.4.2 ad if ((command->flag & CS_OWN) == 0) {
861 1.95.4.2 ad
862 1.64 simonb /*
863 1.64 simonb * Standard syntax:
864 1.64 simonb * command [/modifier] [addr] [,count]
865 1.64 simonb */
866 1.95.4.2 ad t = db_read_token(); /* get modifier */
867 1.95.4.2 ad if (t == tSLASH) {
868 1.64 simonb t = db_read_token();
869 1.64 simonb if (t != tIDENT) {
870 1.64 simonb db_printf("Bad modifier\n");
871 1.64 simonb db_flush_lex();
872 1.64 simonb return;
873 1.64 simonb }
874 1.95.4.2 ad /* save modifier */
875 1.71 itojun strlcpy(modif, db_tok_string, sizeof(modif));
876 1.95.4.2 ad
877 1.64 simonb } else {
878 1.64 simonb db_unread_token(t);
879 1.64 simonb modif[0] = '\0';
880 1.64 simonb }
881 1.64 simonb
882 1.95.4.2 ad if (db_expression(&addr)) { /*get address*/
883 1.64 simonb db_dot = (db_addr_t) addr;
884 1.64 simonb db_last_addr = db_dot;
885 1.95 thorpej have_addr = true;
886 1.64 simonb } else {
887 1.64 simonb addr = (db_expr_t) db_dot;
888 1.95 thorpej have_addr = false;
889 1.64 simonb }
890 1.95.4.2 ad
891 1.64 simonb t = db_read_token();
892 1.95.4.2 ad if (t == tCOMMA) { /*Get count*/
893 1.64 simonb if (!db_expression(&count)) {
894 1.64 simonb db_printf("Count missing\n");
895 1.64 simonb db_flush_lex();
896 1.64 simonb return;
897 1.64 simonb }
898 1.95.4.2 ad } else {
899 1.64 simonb db_unread_token(t);
900 1.64 simonb count = -1;
901 1.64 simonb }
902 1.95.4.2 ad if ((command->flag & CS_MORE) == 0) {
903 1.64 simonb db_skip_to_eol();
904 1.64 simonb }
905 1.1 cgd }
906 1.1 cgd }
907 1.95.4.2 ad
908 1.95.4.2 ad if (command->flag & CS_NOREPEAT) {
909 1.95.4.2 ad *last_cmdp = NULL;
910 1.95.4.2 ad last_count = 0;
911 1.95.4.2 ad } else {
912 1.95.4.2 ad *last_cmdp = command;
913 1.95.4.2 ad last_count = count;
914 1.95.4.2 ad }
915 1.95.4.2 ad
916 1.95.4.2 ad if (command != NULL) {
917 1.1 cgd /*
918 1.64 simonb * Execute the command.
919 1.1 cgd */
920 1.95.4.3 ad if (command->fcn != NULL)
921 1.95.4.3 ad (*command->fcn)(addr, have_addr, count, modif);
922 1.64 simonb
923 1.95.4.2 ad if (command->flag & CS_SET_DOT) {
924 1.64 simonb /*
925 1.64 simonb * If command changes dot, set dot to
926 1.64 simonb * previous address displayed (if 'ed' style).
927 1.64 simonb */
928 1.64 simonb if (db_ed_style)
929 1.64 simonb db_dot = db_prev;
930 1.64 simonb else
931 1.64 simonb db_dot = db_next;
932 1.64 simonb } else {
933 1.64 simonb /*
934 1.64 simonb * If command does not change dot,
935 1.64 simonb * set 'next' location to be the same.
936 1.64 simonb */
937 1.64 simonb db_next = db_dot;
938 1.1 cgd }
939 1.1 cgd }
940 1.1 cgd }
941 1.1 cgd
942 1.95.4.2 ad /*
943 1.95.4.2 ad * Print help for commands
944 1.95.4.2 ad */
945 1.95.4.2 ad static void
946 1.95.4.2 ad db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
947 1.95.4.2 ad const char *modif)
948 1.95.4.2 ad {
949 1.95.4.2 ad
950 1.95.4.2 ad const struct db_cmd_tbl_en_head *list;
951 1.95.4.2 ad const struct db_cmd_tbl_en *list_ent;
952 1.95.4.2 ad const struct db_command *help;
953 1.95.4.2 ad int t, result;
954 1.95.4.2 ad
955 1.95.4.2 ad t = db_read_token();
956 1.95.4.2 ad /* is there another command after the "help"? */
957 1.95.4.2 ad if (t == tIDENT){
958 1.95.4.2 ad
959 1.95.4.2 ad switch(db_get_list_type(db_tok_string)){
960 1.95.4.2 ad
961 1.95.4.2 ad case DDB_BASE_CMD:
962 1.95.4.2 ad list=&db_base_cmd_list;
963 1.95.4.2 ad break;
964 1.95.4.2 ad case DDB_SHOW_CMD:
965 1.95.4.2 ad list=&db_show_cmd_list;
966 1.95.4.2 ad /* read the show subcommand */
967 1.95.4.2 ad t = db_read_token();
968 1.95.4.2 ad
969 1.95.4.2 ad if (t != tIDENT) {
970 1.95.4.2 ad /* no subcommand, print the list */
971 1.95.4.2 ad db_cmd_list(list);
972 1.95.4.2 ad db_flush_lex();
973 1.95.4.2 ad return;
974 1.95.4.2 ad }
975 1.95.4.2 ad
976 1.95.4.2 ad break;
977 1.95.4.2 ad case DDB_MACH_CMD:
978 1.95.4.2 ad list=&db_mach_cmd_list;
979 1.95.4.2 ad /* read machine subcommand */
980 1.95.4.2 ad t = db_read_token();
981 1.95.4.2 ad
982 1.95.4.2 ad if (t != tIDENT) {
983 1.95.4.2 ad /* no subcommand - just print the list */
984 1.95.4.2 ad db_cmd_list(list);
985 1.95.4.2 ad db_flush_lex();
986 1.95.4.2 ad return;
987 1.95.4.2 ad }
988 1.95.4.2 ad break;
989 1.95.4.2 ad
990 1.95.4.2 ad default:
991 1.95.4.2 ad db_printf("No such command\n");
992 1.95.4.2 ad db_flush_lex();
993 1.95.4.2 ad return;
994 1.95.4.2 ad }
995 1.95.4.2 ad COMPAT_RET:
996 1.95.4.2 ad TAILQ_FOREACH(list_ent,list,db_cmd_next){
997 1.95.4.2 ad result = db_cmd_search(db_tok_string, list_ent->db_cmd,
998 1.95.4.2 ad &help);
999 1.95.4.2 ad /* after CMD_UNIQUE only a single command
1000 1.95.4.2 ad name is possible */
1001 1.95.4.2 ad if (result == CMD_UNIQUE)
1002 1.95.4.2 ad break;
1003 1.95.4.2 ad }
1004 1.95.4.2 ad #ifdef DDB_VERBOSE_HELP
1005 1.95.4.2 ad /*print help*/
1006 1.95.4.2 ad
1007 1.95.4.2 ad db_printf("Command: %s\n",help->name);
1008 1.95.4.2 ad
1009 1.95.4.2 ad if (help->cmd_descr != NULL)
1010 1.95.4.2 ad db_printf(" Description: %s\n",help->cmd_descr);
1011 1.95.4.2 ad
1012 1.95.4.2 ad if (help->cmd_arg != NULL)
1013 1.95.4.2 ad db_printf(" Arguments: %s\n",help->cmd_arg);
1014 1.95.4.2 ad
1015 1.95.4.2 ad if (help->cmd_arg_help != NULL)
1016 1.95.4.2 ad db_printf(" Arguments description:\n%s\n",
1017 1.95.4.2 ad help->cmd_arg_help);
1018 1.95.4.2 ad
1019 1.95.4.2 ad if ((help->cmd_arg == NULL) && (help->cmd_descr == NULL))
1020 1.95.4.2 ad db_printf("%s Doesn't have any help message included.\n",
1021 1.95.4.2 ad help->name);
1022 1.95.4.2 ad #endif
1023 1.95.4.2 ad /* check compatibility flag */
1024 1.95.4.2 ad /*
1025 1.95.4.2 ad * The "show all" command table has been merged with the
1026 1.95.4.2 ad * "show" command table - but we want to keep the old UI
1027 1.95.4.2 ad * available. So if we find a CS_COMPAT entry, we read
1028 1.95.4.2 ad * the next token and try again.
1029 1.95.4.2 ad */
1030 1.95.4.2 ad if (help->flag == CS_COMPAT){
1031 1.95.4.2 ad t = db_read_token();
1032 1.95.4.2 ad
1033 1.95.4.2 ad if (t != tIDENT){
1034 1.95.4.2 ad db_cmd_list(list);
1035 1.95.4.2 ad db_flush_lex();
1036 1.95.4.2 ad return;
1037 1.95.4.2 ad }
1038 1.95.4.2 ad
1039 1.95.4.2 ad goto COMPAT_RET;
1040 1.95.4.2 ad /* support only level 2 commands here */
1041 1.95.4.2 ad } else {
1042 1.95.4.2 ad db_skip_to_eol();
1043 1.95.4.2 ad }
1044 1.95.4.2 ad
1045 1.95.4.2 ad } else /* t != tIDENT */
1046 1.95.4.2 ad /* print base commands */
1047 1.95.4.2 ad db_cmd_list(&db_base_cmd_list);
1048 1.95.4.2 ad
1049 1.95.4.2 ad return;
1050 1.95.4.2 ad }
1051 1.4 brezak /*ARGSUSED*/
1052 1.64 simonb static void
1053 1.94 matt db_map_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
1054 1.90 christos const char *modif)
1055 1.64 simonb {
1056 1.95 thorpej bool full = false;
1057 1.64 simonb
1058 1.64 simonb if (modif[0] == 'f')
1059 1.95 thorpej full = true;
1060 1.60 matt
1061 1.95 thorpej if (have_addr == false)
1062 1.66 scw addr = (db_expr_t)(intptr_t) kernel_map;
1063 1.4 brezak
1064 1.66 scw uvm_map_printit((struct vm_map *)(intptr_t) addr, full, db_printf);
1065 1.4 brezak }
1066 1.4 brezak
1067 1.4 brezak /*ARGSUSED*/
1068 1.64 simonb static void
1069 1.94 matt db_malloc_print_cmd(db_expr_t addr, bool have_addr,
1070 1.91 christos db_expr_t count, const char *modif)
1071 1.62 thorpej {
1072 1.64 simonb
1073 1.62 thorpej #ifdef MALLOC_DEBUG
1074 1.62 thorpej if (!have_addr)
1075 1.62 thorpej addr = 0;
1076 1.62 thorpej
1077 1.62 thorpej debug_malloc_printit(db_printf, (vaddr_t) addr);
1078 1.62 thorpej #else
1079 1.62 thorpej db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
1080 1.62 thorpej #endif /* MALLOC_DEBUG */
1081 1.62 thorpej }
1082 1.62 thorpej
1083 1.62 thorpej /*ARGSUSED*/
1084 1.64 simonb static void
1085 1.94 matt db_object_print_cmd(db_expr_t addr, bool have_addr,
1086 1.91 christos db_expr_t count, const char *modif)
1087 1.64 simonb {
1088 1.95 thorpej bool full = false;
1089 1.64 simonb
1090 1.64 simonb if (modif[0] == 'f')
1091 1.95 thorpej full = true;
1092 1.4 brezak
1093 1.66 scw uvm_object_printit((struct uvm_object *)(intptr_t) addr, full,
1094 1.66 scw db_printf);
1095 1.24 mrg }
1096 1.24 mrg
1097 1.24 mrg /*ARGSUSED*/
1098 1.64 simonb static void
1099 1.94 matt db_page_print_cmd(db_expr_t addr, bool have_addr,
1100 1.91 christos db_expr_t count, const char *modif)
1101 1.64 simonb {
1102 1.95 thorpej bool full = false;
1103 1.64 simonb
1104 1.64 simonb if (modif[0] == 'f')
1105 1.95 thorpej full = true;
1106 1.24 mrg
1107 1.66 scw uvm_page_printit((struct vm_page *)(intptr_t) addr, full, db_printf);
1108 1.36 chs }
1109 1.36 chs
1110 1.36 chs /*ARGSUSED*/
1111 1.64 simonb static void
1112 1.94 matt db_show_all_pages(db_expr_t addr, bool have_addr,
1113 1.91 christos db_expr_t count, const char *modif)
1114 1.84 bjh21 {
1115 1.84 bjh21
1116 1.84 bjh21 uvm_page_printall(db_printf);
1117 1.84 bjh21 }
1118 1.84 bjh21
1119 1.84 bjh21 /*ARGSUSED*/
1120 1.84 bjh21 static void
1121 1.94 matt db_buf_print_cmd(db_expr_t addr, bool have_addr,
1122 1.91 christos db_expr_t count, const char *modif)
1123 1.36 chs {
1124 1.95 thorpej bool full = false;
1125 1.64 simonb
1126 1.36 chs if (modif[0] == 'f')
1127 1.95 thorpej full = true;
1128 1.36 chs
1129 1.66 scw vfs_buf_print((struct buf *)(intptr_t) addr, full, db_printf);
1130 1.65 simonb }
1131 1.65 simonb
1132 1.65 simonb /*ARGSUSED*/
1133 1.65 simonb static void
1134 1.94 matt db_event_print_cmd(db_expr_t addr, bool have_addr,
1135 1.91 christos db_expr_t count, const char *modif)
1136 1.65 simonb {
1137 1.95 thorpej bool full = false;
1138 1.65 simonb
1139 1.65 simonb if (modif[0] == 'f')
1140 1.95 thorpej full = true;
1141 1.65 simonb
1142 1.65 simonb event_print(full, db_printf);
1143 1.36 chs }
1144 1.36 chs
1145 1.36 chs /*ARGSUSED*/
1146 1.64 simonb static void
1147 1.94 matt db_vnode_print_cmd(db_expr_t addr, bool have_addr,
1148 1.91 christos db_expr_t count, const char *modif)
1149 1.36 chs {
1150 1.95 thorpej bool full = false;
1151 1.64 simonb
1152 1.36 chs if (modif[0] == 'f')
1153 1.95 thorpej full = true;
1154 1.36 chs
1155 1.66 scw vfs_vnode_print((struct vnode *)(intptr_t) addr, full, db_printf);
1156 1.74 dbj }
1157 1.74 dbj
1158 1.74 dbj static void
1159 1.94 matt db_mount_print_cmd(db_expr_t addr, bool have_addr,
1160 1.91 christos db_expr_t count, const char *modif)
1161 1.74 dbj {
1162 1.95 thorpej bool full = false;
1163 1.74 dbj
1164 1.74 dbj if (modif[0] == 'f')
1165 1.95 thorpej full = true;
1166 1.74 dbj
1167 1.74 dbj vfs_mount_print((struct mount *)(intptr_t) addr, full, db_printf);
1168 1.4 brezak }
1169 1.4 brezak
1170 1.31 thorpej /*ARGSUSED*/
1171 1.64 simonb static void
1172 1.94 matt db_mbuf_print_cmd(db_expr_t addr, bool have_addr,
1173 1.91 christos db_expr_t count, const char *modif)
1174 1.83 yamt {
1175 1.83 yamt
1176 1.83 yamt m_print((const struct mbuf *)(intptr_t) addr, modif, db_printf);
1177 1.83 yamt }
1178 1.83 yamt
1179 1.83 yamt /*ARGSUSED*/
1180 1.83 yamt static void
1181 1.94 matt db_pool_print_cmd(db_expr_t addr, bool have_addr,
1182 1.91 christos db_expr_t count, const char *modif)
1183 1.31 thorpej {
1184 1.64 simonb
1185 1.66 scw pool_printit((struct pool *)(intptr_t) addr, modif, db_printf);
1186 1.51 chs }
1187 1.31 thorpej
1188 1.51 chs /*ARGSUSED*/
1189 1.64 simonb static void
1190 1.94 matt db_namecache_print_cmd(db_expr_t addr, bool have_addr,
1191 1.91 christos db_expr_t count, const char *modif)
1192 1.51 chs {
1193 1.64 simonb
1194 1.66 scw namecache_print((struct vnode *)(intptr_t) addr, db_printf);
1195 1.51 chs }
1196 1.51 chs
1197 1.51 chs /*ARGSUSED*/
1198 1.64 simonb static void
1199 1.94 matt db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
1200 1.91 christos db_expr_t count, const char *modif)
1201 1.51 chs {
1202 1.64 simonb
1203 1.51 chs uvmexp_print(db_printf);
1204 1.31 thorpej }
1205 1.31 thorpej
1206 1.92 ad /*ARGSUSED*/
1207 1.92 ad static void
1208 1.94 matt db_lock_print_cmd(db_expr_t addr, bool have_addr,
1209 1.92 ad db_expr_t count, const char *modif)
1210 1.92 ad {
1211 1.92 ad
1212 1.92 ad lockdebug_lock_print((void *)addr, db_printf);
1213 1.92 ad }
1214 1.92 ad
1215 1.1 cgd /*
1216 1.1 cgd * Call random function:
1217 1.1 cgd * !expr(arg,arg,arg)
1218 1.1 cgd */
1219 1.16 christos /*ARGSUSED*/
1220 1.64 simonb static void
1221 1.94 matt db_fncall(db_expr_t addr, bool have_addr,
1222 1.91 christos db_expr_t count, const char *modif)
1223 1.1 cgd {
1224 1.1 cgd db_expr_t fn_addr;
1225 1.1 cgd #define MAXARGS 11
1226 1.1 cgd db_expr_t args[MAXARGS];
1227 1.1 cgd int nargs = 0;
1228 1.1 cgd db_expr_t retval;
1229 1.64 simonb db_expr_t (*func)(db_expr_t, ...);
1230 1.1 cgd int t;
1231 1.1 cgd
1232 1.1 cgd if (!db_expression(&fn_addr)) {
1233 1.64 simonb db_printf("Bad function\n");
1234 1.64 simonb db_flush_lex();
1235 1.64 simonb return;
1236 1.1 cgd }
1237 1.66 scw func = (db_expr_t (*)(db_expr_t, ...))(intptr_t) fn_addr;
1238 1.1 cgd
1239 1.1 cgd t = db_read_token();
1240 1.1 cgd if (t == tLPAREN) {
1241 1.64 simonb if (db_expression(&args[0])) {
1242 1.64 simonb nargs++;
1243 1.64 simonb while ((t = db_read_token()) == tCOMMA) {
1244 1.64 simonb if (nargs == MAXARGS) {
1245 1.64 simonb db_printf("Too many arguments\n");
1246 1.64 simonb db_flush_lex();
1247 1.64 simonb return;
1248 1.64 simonb }
1249 1.64 simonb if (!db_expression(&args[nargs])) {
1250 1.64 simonb db_printf("Argument missing\n");
1251 1.64 simonb db_flush_lex();
1252 1.64 simonb return;
1253 1.64 simonb }
1254 1.64 simonb nargs++;
1255 1.64 simonb }
1256 1.64 simonb db_unread_token(t);
1257 1.64 simonb }
1258 1.64 simonb if (db_read_token() != tRPAREN) {
1259 1.64 simonb db_printf("?\n");
1260 1.1 cgd db_flush_lex();
1261 1.1 cgd return;
1262 1.1 cgd }
1263 1.1 cgd }
1264 1.1 cgd db_skip_to_eol();
1265 1.1 cgd
1266 1.1 cgd while (nargs < MAXARGS) {
1267 1.64 simonb args[nargs++] = 0;
1268 1.1 cgd }
1269 1.1 cgd
1270 1.1 cgd retval = (*func)(args[0], args[1], args[2], args[3], args[4],
1271 1.20 christos args[5], args[6], args[7], args[8], args[9]);
1272 1.45 jhawk db_printf("%s\n", db_num_to_str(retval));
1273 1.23 scottr }
1274 1.23 scottr
1275 1.64 simonb static void
1276 1.94 matt db_reboot_cmd(db_expr_t addr, bool have_addr,
1277 1.91 christos db_expr_t count, const char *modif)
1278 1.23 scottr {
1279 1.23 scottr db_expr_t bootflags;
1280 1.23 scottr
1281 1.23 scottr /* Flags, default to RB_AUTOBOOT */
1282 1.23 scottr if (!db_expression(&bootflags))
1283 1.23 scottr bootflags = (db_expr_t)RB_AUTOBOOT;
1284 1.23 scottr if (db_read_token() != tEOL) {
1285 1.64 simonb db_error("?\n");
1286 1.64 simonb /*NOTREACHED*/
1287 1.23 scottr }
1288 1.47 sommerfe /*
1289 1.47 sommerfe * We are leaving DDB, never to return upward.
1290 1.47 sommerfe * Clear db_recover so that we can debug faults in functions
1291 1.47 sommerfe * called from cpu_reboot.
1292 1.47 sommerfe */
1293 1.47 sommerfe db_recover = 0;
1294 1.23 scottr cpu_reboot((int)bootflags, NULL);
1295 1.41 jhawk }
1296 1.41 jhawk
1297 1.64 simonb static void
1298 1.94 matt db_sifting_cmd(db_expr_t addr, bool have_addr,
1299 1.91 christos db_expr_t count, const char *modif)
1300 1.41 jhawk {
1301 1.41 jhawk int mode, t;
1302 1.41 jhawk
1303 1.41 jhawk t = db_read_token();
1304 1.41 jhawk if (t == tSLASH) {
1305 1.41 jhawk t = db_read_token();
1306 1.41 jhawk if (t != tIDENT) {
1307 1.41 jhawk bad_modifier:
1308 1.41 jhawk db_printf("Bad modifier\n");
1309 1.41 jhawk db_flush_lex();
1310 1.41 jhawk return;
1311 1.41 jhawk }
1312 1.41 jhawk if (!strcmp(db_tok_string, "F"))
1313 1.41 jhawk mode = 'F';
1314 1.41 jhawk else
1315 1.41 jhawk goto bad_modifier;
1316 1.41 jhawk t = db_read_token();
1317 1.41 jhawk } else
1318 1.41 jhawk mode = 0;
1319 1.41 jhawk
1320 1.51 chs if (t == tIDENT)
1321 1.41 jhawk db_sifting(db_tok_string, mode);
1322 1.41 jhawk else {
1323 1.41 jhawk db_printf("Bad argument (non-string)\n");
1324 1.41 jhawk db_flush_lex();
1325 1.41 jhawk }
1326 1.43 jhawk }
1327 1.43 jhawk
1328 1.64 simonb static void
1329 1.94 matt db_stack_trace_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1330 1.43 jhawk {
1331 1.79 drochner register const char *cp = modif;
1332 1.70 atatat register char c;
1333 1.70 atatat void (*pr)(const char *, ...);
1334 1.70 atatat
1335 1.70 atatat pr = db_printf;
1336 1.70 atatat while ((c = *cp++) != 0)
1337 1.70 atatat if (c == 'l')
1338 1.70 atatat pr = printf;
1339 1.64 simonb
1340 1.43 jhawk if (count == -1)
1341 1.43 jhawk count = 65535;
1342 1.43 jhawk
1343 1.70 atatat db_stack_trace_print(addr, have_addr, count, modif, pr);
1344 1.32 lukem }
1345 1.32 lukem
1346 1.64 simonb static void
1347 1.94 matt db_sync_cmd(db_expr_t addr, bool have_addr,
1348 1.91 christos db_expr_t count, const char *modif)
1349 1.32 lukem {
1350 1.64 simonb
1351 1.47 sommerfe /*
1352 1.47 sommerfe * We are leaving DDB, never to return upward.
1353 1.47 sommerfe * Clear db_recover so that we can debug faults in functions
1354 1.47 sommerfe * called from cpu_reboot.
1355 1.47 sommerfe */
1356 1.47 sommerfe db_recover = 0;
1357 1.32 lukem cpu_reboot(RB_DUMP, NULL);
1358 1.1 cgd }
1359