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