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