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