db_command.c revision 1.114.6.4 1 1.114.6.4 mjf /* $NetBSD: db_command.c,v 1.114.6.4 2008/10/05 20:11:28 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.4 mjf __KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.114.6.4 2008/10/05 20:11:28 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.4 mjf { DDB_ADD_CMD("mqueue", db_show_mqueue_cmd, 0,
250 1.114.6.4 mjf "Print the message queues", NULL, NULL) },
251 1.114.6.2 mjf { DDB_ADD_CMD("mbuf", db_mbuf_print_cmd, 0,NULL,NULL,
252 1.114.6.2 mjf "-c prints all mbuf chains") },
253 1.114.6.2 mjf { DDB_ADD_CMD("ncache", db_namecache_print_cmd, 0,
254 1.114.6.2 mjf "Dump the namecache list.", "address",NULL) },
255 1.114.6.2 mjf { DDB_ADD_CMD("object", db_object_print_cmd, 0,
256 1.114.6.2 mjf "Print the vm_object at address.", "[/f] address",NULL) },
257 1.114.6.2 mjf { DDB_ADD_CMD("page", db_page_print_cmd, 0,
258 1.114.6.2 mjf "Print the vm_page at address.", "[/f] address",NULL) },
259 1.114.6.2 mjf { DDB_ADD_CMD("pool", db_pool_print_cmd, 0,
260 1.114.6.2 mjf "Print the pool at address.", "[/clp] address",NULL) },
261 1.114.6.2 mjf { DDB_ADD_CMD("registers", db_show_regs, 0,
262 1.114.6.2 mjf "Display the register set.", "[/u]",NULL) },
263 1.114.6.2 mjf { DDB_ADD_CMD("sched_qs", db_show_sched_qs, 0,
264 1.114.6.2 mjf "Print the state of the scheduler's run queues.",
265 1.114.6.2 mjf NULL,NULL) },
266 1.114.6.2 mjf { DDB_ADD_CMD("uvmexp", db_uvmexp_print_cmd, 0,
267 1.114.6.2 mjf "Print a selection of UVM counters and statistics.",
268 1.114.6.2 mjf NULL,NULL) },
269 1.114.6.3 mjf #ifdef UVMHIST
270 1.114.6.3 mjf { DDB_ADD_CMD("uvmhist", db_uvmhist_print_cmd, 0,
271 1.114.6.3 mjf "Print the UVM history logs.",
272 1.114.6.3 mjf NULL,NULL) },
273 1.114.6.3 mjf #endif
274 1.114.6.2 mjf { DDB_ADD_CMD("vnode", db_vnode_print_cmd, 0,
275 1.114.6.2 mjf "Print the vnode at address.", "[/f] address",NULL) },
276 1.114.6.2 mjf { DDB_ADD_CMD("watches", db_listwatch_cmd, 0,
277 1.114.6.2 mjf "Display all watchpoints.", NULL,NULL) },
278 1.114.6.2 mjf { DDB_ADD_CMD(NULL, NULL, 0,NULL,NULL,NULL) }
279 1.114.6.2 mjf };
280 1.114.6.2 mjf
281 1.114.6.2 mjf /* arch/<arch>/<arch>/db_interface.c */
282 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
283 1.114.6.2 mjf extern const struct db_command db_machine_command_table[];
284 1.114.6.2 mjf #endif
285 1.114.6.2 mjf
286 1.114.6.2 mjf static const struct db_command db_command_table[] = {
287 1.114.6.2 mjf { DDB_ADD_CMD("b", 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("break", db_breakpoint_cmd, 0,
290 1.114.6.2 mjf "Set a breakpoint at address", "[/u] address[,count].",NULL) },
291 1.114.6.2 mjf { DDB_ADD_CMD("bt", db_stack_trace_cmd, 0,
292 1.114.6.2 mjf "Show backtrace.", "See help trace.",NULL) },
293 1.114.6.2 mjf { DDB_ADD_CMD("c", db_continue_cmd, 0,
294 1.114.6.2 mjf "Continue execution.", "[/c]",NULL) },
295 1.114.6.2 mjf { DDB_ADD_CMD("call", db_fncall, CS_OWN,
296 1.114.6.2 mjf "Call the function", "address[(expression[,...])]",NULL) },
297 1.114.6.2 mjf { DDB_ADD_CMD("callout", db_show_callout, 0, NULL,
298 1.114.6.2 mjf NULL,NULL ) },
299 1.114.6.2 mjf { DDB_ADD_CMD("continue", db_continue_cmd, 0,
300 1.114.6.2 mjf "Continue execution.", "[/c]",NULL) },
301 1.114.6.2 mjf { DDB_ADD_CMD("d", 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("delete", db_delete_cmd, 0,
304 1.114.6.2 mjf "Delete a breakpoint.", "address | #number",NULL) },
305 1.114.6.2 mjf { DDB_ADD_CMD("dmesg", db_dmesg, 0,
306 1.114.6.2 mjf "Show kernel message buffer.", "[count]",NULL) },
307 1.114.6.2 mjf { DDB_ADD_CMD("dwatch", db_deletewatch_cmd, 0,
308 1.114.6.2 mjf "Delete the watchpoint.", "address",NULL) },
309 1.114.6.2 mjf { DDB_ADD_CMD("examine", db_examine_cmd, CS_SET_DOT,
310 1.114.6.2 mjf "Display the address locations.",
311 1.114.6.2 mjf "[/modifier] address[,count]",NULL) },
312 1.114.6.2 mjf { DDB_ADD_CMD("help", db_help_print_cmd, CS_OWN|CS_NOREPEAT,
313 1.114.6.2 mjf "Display help about commands",
314 1.114.6.2 mjf "Use other commands as arguments.",NULL) },
315 1.114.6.2 mjf { DDB_ADD_CMD("kill", db_kill_proc, CS_OWN,
316 1.114.6.2 mjf "Send a signal to the process","pid[,signal_number]",
317 1.114.6.2 mjf " pid:\t\t\tthe process id (may need 0t prefix for decimal)\n"
318 1.114.6.2 mjf " signal_number:\tthe signal to send") },
319 1.114.6.2 mjf #ifdef KGDB
320 1.114.6.2 mjf { DDB_ADD_CMD("kgdb", db_kgdb_cmd, 0, NULL,NULL,NULL) },
321 1.114.6.2 mjf #endif
322 1.114.6.2 mjf { DDB_ADD_CMD("machine",NULL,CS_MACH,
323 1.114.6.2 mjf "Architecture specific functions.",NULL,NULL) },
324 1.114.6.2 mjf { DDB_ADD_CMD("match", db_trace_until_matching_cmd,0,
325 1.114.6.2 mjf "Stop at the matching return instruction.","See help next",NULL) },
326 1.114.6.2 mjf { DDB_ADD_CMD("next", db_trace_until_matching_cmd,0,
327 1.114.6.2 mjf "Stop at the matching return instruction.","[/p]",NULL) },
328 1.114.6.2 mjf { DDB_ADD_CMD("p", db_print_cmd, 0,
329 1.114.6.2 mjf "Print address according to the format.",
330 1.114.6.2 mjf "[/axzodurc] address [address ...]",NULL) },
331 1.114.6.2 mjf { DDB_ADD_CMD("print", db_print_cmd, 0,
332 1.114.6.2 mjf "Print address according to the format.",
333 1.114.6.2 mjf "[/axzodurc] address [address ...]",NULL) },
334 1.114.6.2 mjf { DDB_ADD_CMD("ps", db_show_all_procs, 0,
335 1.114.6.2 mjf "Print all processes.","See show all procs",NULL) },
336 1.114.6.2 mjf { DDB_ADD_CMD("reboot", db_reboot_cmd, CS_OWN,
337 1.114.6.2 mjf "Reboot","0x1 RB_ASKNAME, 0x2 RB_SINGLE, 0x4 RB_NOSYNC, 0x8 RB_HALT,"
338 1.114.6.2 mjf "0x40 RB_KDB, 0x100 RB_DUMP, 0x808 RB_POWERDOWN",NULL) },
339 1.114.6.2 mjf { DDB_ADD_CMD("s", db_single_step_cmd, 0,
340 1.114.6.2 mjf "Single-step count times.","[/p] [,count]",NULL) },
341 1.114.6.2 mjf { DDB_ADD_CMD("search", db_search_cmd, CS_OWN|CS_SET_DOT,
342 1.114.6.2 mjf "Search memory from address for value.",
343 1.114.6.2 mjf "[/bhl] address value [mask] [,count]",NULL) },
344 1.114.6.2 mjf { DDB_ADD_CMD("set", db_set_cmd, CS_OWN,
345 1.114.6.2 mjf "Set the named variable","$variable [=] expression",NULL) },
346 1.114.6.2 mjf { DDB_ADD_CMD("show", NULL, CS_SHOW,
347 1.114.6.2 mjf "Show kernel stats.", NULL,NULL) },
348 1.114.6.2 mjf { DDB_ADD_CMD("sifting", db_sifting_cmd, CS_OWN,
349 1.114.6.2 mjf "Search the symbol tables ","[/F] string",NULL) },
350 1.114.6.2 mjf { DDB_ADD_CMD("step", db_single_step_cmd, 0,
351 1.114.6.2 mjf "Single-step count times.","[/p] [,count]",NULL) },
352 1.114.6.2 mjf { DDB_ADD_CMD("sync", db_sync_cmd, CS_OWN,
353 1.114.6.2 mjf "Force a crash dump, and then reboot.",NULL,NULL) },
354 1.114.6.2 mjf { DDB_ADD_CMD("trace", db_stack_trace_cmd, 0,
355 1.114.6.2 mjf "Stack trace from frame-address.",
356 1.114.6.2 mjf "[/u[l]] [frame-address][,count]",NULL) },
357 1.114.6.2 mjf { DDB_ADD_CMD("until", db_trace_until_call_cmd,0,
358 1.114.6.2 mjf "Stop at the next call or return instruction.","[/p]",NULL) },
359 1.114.6.2 mjf { DDB_ADD_CMD("w", db_write_cmd, CS_MORE|CS_SET_DOT,
360 1.114.6.2 mjf "Write the expressions at succeeding locations.",
361 1.114.6.2 mjf "[/bhl] address expression [expression ...]",NULL) },
362 1.114.6.2 mjf { DDB_ADD_CMD("watch", db_watchpoint_cmd, CS_MORE,
363 1.114.6.2 mjf "Set a watchpoint for a region. ","address[,size]",NULL) },
364 1.114.6.2 mjf { DDB_ADD_CMD("whatis", db_whatis_cmd, 0,
365 1.114.6.2 mjf "Describe what an address is", "address", NULL) },
366 1.114.6.2 mjf { DDB_ADD_CMD("write", db_write_cmd, CS_MORE|CS_SET_DOT,
367 1.114.6.2 mjf "Write the expressions at succeeding locations.",
368 1.114.6.2 mjf "[/bhl] address expression [expression ...]",NULL) },
369 1.114.6.2 mjf { DDB_ADD_CMD("x", db_examine_cmd, CS_SET_DOT,
370 1.114.6.2 mjf "Display the address locations.",
371 1.114.6.2 mjf "[/modifier] address[,count]",NULL) },
372 1.114.6.2 mjf { DDB_ADD_CMD(NULL, NULL, 0, NULL, NULL, NULL) }
373 1.114.6.2 mjf };
374 1.114.6.2 mjf
375 1.114.6.2 mjf static const struct db_command *db_last_command = NULL;
376 1.114.6.2 mjf #if defined(DDB_COMMANDONENTER)
377 1.114.6.2 mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = ___STRING(DDB_COMMANDONENTER);
378 1.114.6.2 mjf #else /* defined(DDB_COMMANDONENTER) */
379 1.114.6.2 mjf char db_cmd_on_enter[DB_LINE_MAXLEN + 1] = "";
380 1.114.6.2 mjf #endif /* defined(DDB_COMMANDONENTER) */
381 1.114.6.2 mjf #define DB_LINE_SEP ';'
382 1.114.6.2 mjf
383 1.114.6.2 mjf /*
384 1.114.6.2 mjf * Utility routine - discard tokens through end-of-line.
385 1.114.6.2 mjf */
386 1.114.6.2 mjf void
387 1.114.6.2 mjf db_skip_to_eol(void)
388 1.114.6.2 mjf {
389 1.114.6.2 mjf int t;
390 1.114.6.2 mjf
391 1.114.6.2 mjf do {
392 1.114.6.2 mjf t = db_read_token();
393 1.114.6.2 mjf } while (t != tEOL);
394 1.114.6.2 mjf }
395 1.114.6.2 mjf
396 1.114.6.2 mjf void
397 1.114.6.2 mjf db_error(const char *s)
398 1.114.6.2 mjf {
399 1.114.6.2 mjf
400 1.114.6.2 mjf if (s)
401 1.114.6.2 mjf db_printf("%s", s);
402 1.114.6.2 mjf db_flush_lex();
403 1.114.6.2 mjf longjmp(db_recover);
404 1.114.6.2 mjf }
405 1.114.6.2 mjf
406 1.114.6.2 mjf /*Execute commandlist after ddb start
407 1.114.6.2 mjf *This function goes through the command list created from commands and ';'
408 1.114.6.2 mjf */
409 1.114.6.2 mjf
410 1.114.6.2 mjf static void
411 1.114.6.2 mjf db_execute_commandlist(const char *cmdlist)
412 1.114.6.2 mjf {
413 1.114.6.2 mjf const char *cmd = cmdlist;
414 1.114.6.2 mjf const struct db_command *dummy = NULL;
415 1.114.6.2 mjf
416 1.114.6.2 mjf while (*cmd != '\0') {
417 1.114.6.2 mjf const char *ep = cmd;
418 1.114.6.2 mjf
419 1.114.6.2 mjf while (*ep != '\0' && *ep != DB_LINE_SEP) {
420 1.114.6.2 mjf ep++;
421 1.114.6.2 mjf }
422 1.114.6.2 mjf db_set_line(cmd, ep);
423 1.114.6.2 mjf db_command(&dummy);
424 1.114.6.2 mjf cmd = ep;
425 1.114.6.2 mjf if (*cmd == DB_LINE_SEP) {
426 1.114.6.2 mjf cmd++;
427 1.114.6.2 mjf }
428 1.114.6.2 mjf }
429 1.114.6.2 mjf }
430 1.114.6.2 mjf
431 1.114.6.2 mjf /*Initialize ddb command tables*/
432 1.114.6.2 mjf void
433 1.114.6.2 mjf db_init_commands(void)
434 1.114.6.2 mjf {
435 1.114.6.2 mjf static bool done = false;
436 1.114.6.2 mjf
437 1.114.6.2 mjf if (done) return;
438 1.114.6.2 mjf done = true;
439 1.114.6.2 mjf
440 1.114.6.2 mjf /* register command tables */
441 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_BASE_CMD, &db_base_cmd_builtins);
442 1.114.6.2 mjf #ifdef DB_MACHINE_COMMANDS
443 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_MACH_CMD, &db_mach_cmd_builtins);
444 1.114.6.2 mjf #endif
445 1.114.6.2 mjf (void)db_register_tbl_entry(DDB_SHOW_CMD, &db_show_cmd_builtins);
446 1.114.6.2 mjf }
447 1.114.6.2 mjf
448 1.114.6.2 mjf
449 1.114.6.2 mjf /*
450 1.114.6.2 mjf * Add command table to the specified list
451 1.114.6.2 mjf * Arg:
452 1.114.6.2 mjf * int type specifies type of command table DDB_SHOW_CMD|DDB_BASE_CMD|DDB_MAC_CMD
453 1.114.6.2 mjf * *cmd_tbl poiter to static allocated db_command table
454 1.114.6.2 mjf *
455 1.114.6.2 mjf *Command table must be NULL terminated array of struct db_command
456 1.114.6.2 mjf */
457 1.114.6.2 mjf int
458 1.114.6.2 mjf db_register_tbl(uint8_t type, const struct db_command *cmd_tbl)
459 1.114.6.2 mjf {
460 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
461 1.114.6.2 mjf
462 1.114.6.2 mjf if (cmd_tbl->name == 0)
463 1.114.6.2 mjf /* empty list - ignore */
464 1.114.6.2 mjf return 0;
465 1.114.6.2 mjf
466 1.114.6.2 mjf /* force builtin commands to be registered first */
467 1.114.6.2 mjf db_init_commands();
468 1.114.6.2 mjf
469 1.114.6.2 mjf /* now create a list entry for this table */
470 1.114.6.2 mjf list_ent = malloc(sizeof(struct db_cmd_tbl_en), M_TEMP, M_ZERO);
471 1.114.6.2 mjf if (list_ent == NULL)
472 1.114.6.2 mjf return ENOMEM;
473 1.114.6.2 mjf list_ent->db_cmd=cmd_tbl;
474 1.114.6.2 mjf
475 1.114.6.2 mjf /* and register it */
476 1.114.6.2 mjf return db_register_tbl_entry(type, list_ent);
477 1.114.6.2 mjf }
478 1.114.6.2 mjf
479 1.114.6.2 mjf static int
480 1.114.6.2 mjf db_register_tbl_entry(uint8_t type, struct db_cmd_tbl_en *list_ent)
481 1.114.6.2 mjf {
482 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
483 1.114.6.2 mjf
484 1.114.6.2 mjf switch(type) {
485 1.114.6.2 mjf case DDB_BASE_CMD:
486 1.114.6.2 mjf list = &db_base_cmd_list;
487 1.114.6.2 mjf break;
488 1.114.6.2 mjf case DDB_SHOW_CMD:
489 1.114.6.2 mjf list = &db_show_cmd_list;
490 1.114.6.2 mjf break;
491 1.114.6.2 mjf case DDB_MACH_CMD:
492 1.114.6.2 mjf list = &db_mach_cmd_list;
493 1.114.6.2 mjf break;
494 1.114.6.2 mjf default:
495 1.114.6.2 mjf return ENOENT;
496 1.114.6.2 mjf }
497 1.114.6.2 mjf
498 1.114.6.2 mjf TAILQ_INSERT_TAIL(list, list_ent, db_cmd_next);
499 1.114.6.2 mjf
500 1.114.6.2 mjf return 0;
501 1.114.6.2 mjf }
502 1.114.6.2 mjf
503 1.114.6.2 mjf /*
504 1.114.6.2 mjf * Remove command table specified with db_cmd address == cmd_tbl
505 1.114.6.2 mjf */
506 1.114.6.2 mjf int
507 1.114.6.2 mjf db_unregister_tbl(uint8_t type,const struct db_command *cmd_tbl)
508 1.114.6.2 mjf {
509 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
510 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
511 1.114.6.2 mjf
512 1.114.6.2 mjf /* find list on which the entry should live */
513 1.114.6.2 mjf switch (type) {
514 1.114.6.2 mjf case DDB_BASE_CMD:
515 1.114.6.2 mjf list=&db_base_cmd_list;
516 1.114.6.2 mjf break;
517 1.114.6.2 mjf case DDB_SHOW_CMD:
518 1.114.6.2 mjf list=&db_show_cmd_list;
519 1.114.6.2 mjf break;
520 1.114.6.2 mjf case DDB_MACH_CMD:
521 1.114.6.2 mjf list=&db_mach_cmd_list;
522 1.114.6.2 mjf break;
523 1.114.6.2 mjf default:
524 1.114.6.2 mjf return EINVAL;
525 1.114.6.2 mjf }
526 1.114.6.2 mjf
527 1.114.6.2 mjf TAILQ_FOREACH (list_ent,list,db_cmd_next) {
528 1.114.6.2 mjf if (list_ent->db_cmd == cmd_tbl){
529 1.114.6.2 mjf TAILQ_REMOVE(list,
530 1.114.6.2 mjf list_ent,db_cmd_next);
531 1.114.6.2 mjf free(list_ent,M_TEMP);
532 1.114.6.2 mjf return 0;
533 1.114.6.2 mjf }
534 1.114.6.2 mjf }
535 1.114.6.2 mjf return ENOENT;
536 1.114.6.3 mjf }
537 1.114.6.2 mjf
538 1.114.6.2 mjf /*This function is called from machine trap code.*/
539 1.114.6.2 mjf void
540 1.114.6.2 mjf db_command_loop(void)
541 1.114.6.2 mjf {
542 1.114.6.3 mjf
543 1.114.6.2 mjf label_t db_jmpbuf;
544 1.114.6.2 mjf label_t *savejmp;
545 1.114.6.2 mjf
546 1.114.6.2 mjf /*
547 1.114.6.2 mjf * Initialize 'prev' and 'next' to dot.
548 1.114.6.2 mjf */
549 1.114.6.2 mjf db_prev = db_dot;
550 1.114.6.2 mjf db_next = db_dot;
551 1.114.6.2 mjf
552 1.114.6.2 mjf db_cmd_loop_done = false;
553 1.114.6.2 mjf
554 1.114.6.2 mjf /*Init default command tables add machine, base,
555 1.114.6.2 mjf show command tables to the list*/
556 1.114.6.2 mjf db_init_commands();
557 1.114.6.2 mjf
558 1.114.6.2 mjf /*save context for return from ddb*/
559 1.114.6.2 mjf savejmp = db_recover;
560 1.114.6.2 mjf db_recover = &db_jmpbuf;
561 1.114.6.2 mjf (void) setjmp(&db_jmpbuf);
562 1.114.6.2 mjf
563 1.114.6.2 mjf /*Execute default ddb start commands*/
564 1.114.6.2 mjf db_execute_commandlist(db_cmd_on_enter);
565 1.114.6.2 mjf
566 1.114.6.2 mjf (void) setjmp(&db_jmpbuf);
567 1.114.6.2 mjf while (!db_cmd_loop_done) {
568 1.114.6.2 mjf if (db_print_position() != 0)
569 1.114.6.2 mjf db_printf("\n");
570 1.114.6.2 mjf db_output_line = 0;
571 1.114.6.2 mjf
572 1.114.6.2 mjf
573 1.114.6.2 mjf #ifdef MULTIPROCESSOR
574 1.114.6.2 mjf db_printf("db{%ld}> ", (long)cpu_number());
575 1.114.6.2 mjf #else
576 1.114.6.2 mjf db_printf("db> ");
577 1.114.6.2 mjf #endif
578 1.114.6.2 mjf (void) db_read_line();
579 1.114.6.2 mjf
580 1.114.6.2 mjf db_command(&db_last_command);
581 1.114.6.2 mjf }
582 1.114.6.2 mjf
583 1.114.6.2 mjf db_recover = savejmp;
584 1.114.6.2 mjf }
585 1.114.6.2 mjf
586 1.114.6.2 mjf /*
587 1.114.6.2 mjf * Search for command table for command prefix
588 1.114.6.2 mjf * ret: CMD_UNIQUE -> completely matches command
589 1.114.6.2 mjf * CMD_FOUND -> matches prefix of single command
590 1.114.6.2 mjf * CMD_AMBIGIOUS -> matches prefix of more than one command
591 1.114.6.2 mjf * CMD_NONE -> command not found
592 1.114.6.2 mjf */
593 1.114.6.2 mjf static int
594 1.114.6.2 mjf db_cmd_search(const char *name,const struct db_command *table,
595 1.114.6.2 mjf const struct db_command **cmdp)
596 1.114.6.2 mjf {
597 1.114.6.3 mjf
598 1.114.6.2 mjf const struct db_command *cmd;
599 1.114.6.2 mjf int result;
600 1.114.6.2 mjf
601 1.114.6.2 mjf result = CMD_NONE;
602 1.114.6.2 mjf *cmdp = NULL;
603 1.114.6.2 mjf for (cmd = table; cmd->name != 0; cmd++) {
604 1.114.6.2 mjf const char *lp;
605 1.114.6.2 mjf const char *rp;
606 1.114.6.2 mjf
607 1.114.6.2 mjf lp = name;
608 1.114.6.2 mjf rp = cmd->name;
609 1.114.6.2 mjf while (*lp != '\0' && *lp == *rp) {
610 1.114.6.2 mjf rp++;
611 1.114.6.2 mjf lp++;
612 1.114.6.2 mjf }
613 1.114.6.2 mjf
614 1.114.6.2 mjf if (*lp != '\0') /* mismatch or extra chars in name */
615 1.114.6.2 mjf continue;
616 1.114.6.2 mjf
617 1.114.6.2 mjf if (*rp == '\0') { /* complete match */
618 1.114.6.2 mjf *cmdp = cmd;
619 1.114.6.2 mjf return (CMD_UNIQUE);
620 1.114.6.2 mjf }
621 1.114.6.2 mjf
622 1.114.6.2 mjf /* prefix match: end of name, not end of command */
623 1.114.6.2 mjf if (result == CMD_NONE) {
624 1.114.6.2 mjf result = CMD_FOUND;
625 1.114.6.2 mjf *cmdp = cmd;
626 1.114.6.2 mjf }
627 1.114.6.2 mjf else if (result == CMD_FOUND) {
628 1.114.6.2 mjf result = CMD_AMBIGUOUS;
629 1.114.6.2 mjf *cmdp = NULL;
630 1.114.6.2 mjf }
631 1.114.6.2 mjf }
632 1.114.6.2 mjf
633 1.114.6.2 mjf return (result);
634 1.114.6.2 mjf }
635 1.114.6.2 mjf
636 1.114.6.2 mjf /*
637 1.114.6.2 mjf *List commands to the console.
638 1.114.6.2 mjf */
639 1.114.6.2 mjf static void
640 1.114.6.2 mjf db_cmd_list(const struct db_cmd_tbl_en_head *list)
641 1.114.6.2 mjf {
642 1.114.6.2 mjf
643 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
644 1.114.6.2 mjf const struct db_command *table;
645 1.114.6.2 mjf size_t i, j, w, columns, lines, numcmds, width=0;
646 1.114.6.2 mjf const char *p;
647 1.114.6.2 mjf
648 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next) {
649 1.114.6.2 mjf table = list_ent->db_cmd;
650 1.114.6.2 mjf for (i = 0; table[i].name != NULL; i++) {
651 1.114.6.2 mjf w = strlen(table[i].name);
652 1.114.6.2 mjf if (w > width)
653 1.114.6.2 mjf width = w;
654 1.114.6.2 mjf }
655 1.114.6.2 mjf }
656 1.114.6.2 mjf
657 1.114.6.2 mjf width = DB_NEXT_TAB(width);
658 1.114.6.2 mjf
659 1.114.6.2 mjf columns = db_max_width / width;
660 1.114.6.2 mjf if (columns == 0)
661 1.114.6.2 mjf columns = 1;
662 1.114.6.2 mjf
663 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next) {
664 1.114.6.2 mjf table = list_ent->db_cmd;
665 1.114.6.2 mjf
666 1.114.6.2 mjf for (numcmds = 0; table[numcmds].name != NULL; numcmds++)
667 1.114.6.2 mjf ;
668 1.114.6.2 mjf lines = (numcmds + columns - 1) / columns;
669 1.114.6.3 mjf
670 1.114.6.2 mjf for (i = 0; i < lines; i++) {
671 1.114.6.2 mjf for (j = 0; j < columns; j++) {
672 1.114.6.2 mjf p = table[j * lines + i].name;
673 1.114.6.2 mjf if (p)
674 1.114.6.2 mjf db_printf("%s", p);
675 1.114.6.2 mjf if (j * lines + i + lines >= numcmds) {
676 1.114.6.2 mjf db_putchar('\n');
677 1.114.6.2 mjf break;
678 1.114.6.2 mjf }
679 1.114.6.2 mjf if (p) {
680 1.114.6.2 mjf w = strlen(p);
681 1.114.6.2 mjf while (w < width) {
682 1.114.6.2 mjf w = DB_NEXT_TAB(w);
683 1.114.6.2 mjf db_putchar('\t');
684 1.114.6.2 mjf }
685 1.114.6.2 mjf }
686 1.114.6.2 mjf }
687 1.114.6.2 mjf }
688 1.114.6.2 mjf }
689 1.114.6.2 mjf return;
690 1.114.6.2 mjf }
691 1.114.6.2 mjf
692 1.114.6.2 mjf /*
693 1.114.6.2 mjf *Returns type of list for command with name *name.
694 1.114.6.2 mjf */
695 1.114.6.2 mjf static int
696 1.114.6.2 mjf db_get_list_type(const char *name)
697 1.114.6.2 mjf {
698 1.114.6.2 mjf
699 1.114.6.2 mjf const struct db_command *cmd;
700 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
701 1.114.6.2 mjf int error,ret=-1;
702 1.114.6.2 mjf
703 1.114.6.2 mjf /* search for the command name */
704 1.114.6.2 mjf TAILQ_FOREACH(list_ent,&db_base_cmd_list,db_cmd_next) {
705 1.114.6.2 mjf /*
706 1.114.6.2 mjf * cmd_search returns CMD_UNIQUE, CMD_FOUND ...
707 1.114.6.2 mjf * CMD_UNIQUE when name was completly matched to cmd->name
708 1.114.6.2 mjf * CMD_FOUND when name was only partially matched to cmd->name
709 1.114.6.2 mjf * CMD_NONE command not found in a list
710 1.114.6.2 mjf * CMD_AMBIGIOUS ->more partialy matches
711 1.114.6.2 mjf */
712 1.114.6.2 mjf
713 1.114.6.2 mjf error = db_cmd_search(name, list_ent->db_cmd, &cmd);
714 1.114.6.2 mjf
715 1.114.6.2 mjf if (error == CMD_UNIQUE) {
716 1.114.6.2 mjf /* exact match found */
717 1.114.6.2 mjf if (cmd->flag == CS_SHOW) {
718 1.114.6.2 mjf ret = DDB_SHOW_CMD;
719 1.114.6.2 mjf break;
720 1.114.6.2 mjf }
721 1.114.6.2 mjf if (cmd->flag == CS_MACH) {
722 1.114.6.2 mjf ret = DDB_MACH_CMD;
723 1.114.6.2 mjf break;
724 1.114.6.2 mjf } else {
725 1.114.6.2 mjf ret = DDB_BASE_CMD;
726 1.114.6.2 mjf break;
727 1.114.6.2 mjf }
728 1.114.6.2 mjf
729 1.114.6.2 mjf } else if (error == CMD_FOUND) {
730 1.114.6.2 mjf /*
731 1.114.6.2 mjf * partial match, search will continue, but
732 1.114.6.2 mjf * note current result in case we won't
733 1.114.6.2 mjf * find anything better.
734 1.114.6.2 mjf */
735 1.114.6.2 mjf if (cmd->flag == CS_SHOW)
736 1.114.6.2 mjf ret = DDB_SHOW_CMD;
737 1.114.6.2 mjf else if (cmd->flag == CS_MACH)
738 1.114.6.2 mjf ret = DDB_MACH_CMD;
739 1.114.6.2 mjf else
740 1.114.6.2 mjf ret = DDB_BASE_CMD;
741 1.114.6.2 mjf }
742 1.114.6.2 mjf }
743 1.114.6.2 mjf
744 1.114.6.2 mjf return ret;
745 1.114.6.2 mjf }
746 1.114.6.2 mjf
747 1.114.6.2 mjf /*
748 1.114.6.2 mjf *Parse command line and execute apropriate function.
749 1.114.6.2 mjf */
750 1.114.6.2 mjf static void
751 1.114.6.2 mjf db_command(const struct db_command **last_cmdp)
752 1.114.6.2 mjf {
753 1.114.6.2 mjf const struct db_command *command;
754 1.114.6.2 mjf struct db_cmd_tbl_en *list_ent;
755 1.114.6.2 mjf struct db_cmd_tbl_en_head *list;
756 1.114.6.3 mjf
757 1.114.6.2 mjf int t;
758 1.114.6.2 mjf int result;
759 1.114.6.3 mjf
760 1.114.6.2 mjf char modif[TOK_STRING_SIZE];
761 1.114.6.2 mjf db_expr_t addr, count;
762 1.114.6.2 mjf bool have_addr = false;
763 1.114.6.2 mjf
764 1.114.6.2 mjf static db_expr_t last_count = 0;
765 1.114.6.3 mjf
766 1.114.6.2 mjf command = NULL; /* XXX gcc */
767 1.114.6.2 mjf
768 1.114.6.2 mjf t = db_read_token();
769 1.114.6.2 mjf if ((t == tEOL) || (t == tCOMMA)) {
770 1.114.6.2 mjf /*
771 1.114.6.2 mjf * An empty line repeats last command, at 'next'.
772 1.114.6.2 mjf * Only a count repeats the last command with the new count.
773 1.114.6.2 mjf */
774 1.114.6.2 mjf command = *last_cmdp;
775 1.114.6.2 mjf
776 1.114.6.2 mjf if (!command)
777 1.114.6.2 mjf return;
778 1.114.6.2 mjf
779 1.114.6.2 mjf addr = (db_expr_t)db_next;
780 1.114.6.2 mjf if (t == tCOMMA) {
781 1.114.6.2 mjf if (!db_expression(&count)) {
782 1.114.6.2 mjf db_printf("Count missing\n");
783 1.114.6.2 mjf db_flush_lex();
784 1.114.6.2 mjf return;
785 1.114.6.2 mjf }
786 1.114.6.2 mjf } else
787 1.114.6.2 mjf count = last_count;
788 1.114.6.2 mjf have_addr = false;
789 1.114.6.2 mjf modif[0] = '\0';
790 1.114.6.2 mjf db_skip_to_eol();
791 1.114.6.2 mjf
792 1.114.6.2 mjf } else if (t == tEXCL) {
793 1.114.6.2 mjf db_fncall(0, 0, 0, NULL);
794 1.114.6.2 mjf return;
795 1.114.6.2 mjf
796 1.114.6.2 mjf } else if (t != tIDENT) {
797 1.114.6.2 mjf db_printf("?\n");
798 1.114.6.2 mjf db_flush_lex();
799 1.114.6.2 mjf return;
800 1.114.6.2 mjf
801 1.114.6.2 mjf } else {
802 1.114.6.2 mjf
803 1.114.6.2 mjf switch(db_get_list_type(db_tok_string)) {
804 1.114.6.2 mjf
805 1.114.6.2 mjf case DDB_BASE_CMD:
806 1.114.6.2 mjf list = &db_base_cmd_list;
807 1.114.6.2 mjf break;
808 1.114.6.2 mjf
809 1.114.6.2 mjf case DDB_SHOW_CMD:
810 1.114.6.2 mjf list = &db_show_cmd_list;
811 1.114.6.2 mjf /* need to read show subcommand if show command list
812 1.114.6.2 mjf is used. */
813 1.114.6.2 mjf t = db_read_token();
814 1.114.6.2 mjf
815 1.114.6.2 mjf if (t != tIDENT) {
816 1.114.6.2 mjf /* if only show command is executed, print
817 1.114.6.2 mjf all subcommands */
818 1.114.6.3 mjf db_cmd_list(list);
819 1.114.6.2 mjf db_flush_lex();
820 1.114.6.2 mjf return;
821 1.114.6.2 mjf }
822 1.114.6.2 mjf break;
823 1.114.6.2 mjf case DDB_MACH_CMD:
824 1.114.6.2 mjf list = &db_mach_cmd_list;
825 1.114.6.2 mjf /* need to read machine subcommand if
826 1.114.6.2 mjf machine level 2 command list is used. */
827 1.114.6.2 mjf t = db_read_token();
828 1.114.6.2 mjf
829 1.114.6.2 mjf if (t != tIDENT) {
830 1.114.6.2 mjf /* if only show command is executed, print
831 1.114.6.2 mjf all subcommands */
832 1.114.6.2 mjf db_cmd_list(list);
833 1.114.6.2 mjf db_flush_lex();
834 1.114.6.2 mjf return;
835 1.114.6.3 mjf }
836 1.114.6.2 mjf break;
837 1.114.6.2 mjf default:
838 1.114.6.2 mjf db_printf("No such command\n");
839 1.114.6.3 mjf db_flush_lex();
840 1.114.6.2 mjf return;
841 1.114.6.2 mjf }
842 1.114.6.2 mjf
843 1.114.6.2 mjf COMPAT_RET:
844 1.114.6.2 mjf TAILQ_FOREACH(list_ent, list, db_cmd_next) {
845 1.114.6.2 mjf result = db_cmd_search(db_tok_string, list_ent->db_cmd,
846 1.114.6.2 mjf &command);
847 1.114.6.2 mjf
848 1.114.6.2 mjf /* after CMD_UNIQUE in cmd_list only a single command
849 1.114.6.2 mjf name is possible */
850 1.114.6.2 mjf if (result == CMD_UNIQUE)
851 1.114.6.2 mjf break;
852 1.114.6.2 mjf
853 1.114.6.2 mjf }
854 1.114.6.2 mjf
855 1.114.6.3 mjf /* check compatibility flag */
856 1.114.6.2 mjf if (command && command->flag & CS_COMPAT){
857 1.114.6.2 mjf t = db_read_token();
858 1.114.6.2 mjf if (t != tIDENT) {
859 1.114.6.2 mjf db_cmd_list(list);
860 1.114.6.2 mjf db_flush_lex();
861 1.114.6.2 mjf return;
862 1.114.6.2 mjf }
863 1.114.6.2 mjf
864 1.114.6.2 mjf /* support only level 2 commands here */
865 1.114.6.2 mjf goto COMPAT_RET;
866 1.114.6.2 mjf }
867 1.114.6.2 mjf
868 1.114.6.2 mjf if (!command) {
869 1.114.6.2 mjf db_printf("No such command\n");
870 1.114.6.2 mjf db_flush_lex();
871 1.114.6.2 mjf return;
872 1.114.6.2 mjf }
873 1.114.6.2 mjf
874 1.114.6.2 mjf if ((command->flag & CS_OWN) == 0) {
875 1.114.6.2 mjf
876 1.114.6.2 mjf /*
877 1.114.6.2 mjf * Standard syntax:
878 1.114.6.2 mjf * command [/modifier] [addr] [,count]
879 1.114.6.2 mjf */
880 1.114.6.2 mjf t = db_read_token(); /* get modifier */
881 1.114.6.3 mjf if (t == tSLASH) {
882 1.114.6.2 mjf t = db_read_token();
883 1.114.6.2 mjf if (t != tIDENT) {
884 1.114.6.2 mjf db_printf("Bad modifier\n");
885 1.114.6.2 mjf db_flush_lex();
886 1.114.6.2 mjf return;
887 1.114.6.2 mjf }
888 1.114.6.2 mjf /* save modifier */
889 1.114.6.2 mjf strlcpy(modif, db_tok_string, sizeof(modif));
890 1.114.6.3 mjf
891 1.114.6.2 mjf } else {
892 1.114.6.2 mjf db_unread_token(t);
893 1.114.6.2 mjf modif[0] = '\0';
894 1.114.6.2 mjf }
895 1.114.6.2 mjf
896 1.114.6.2 mjf if (db_expression(&addr)) { /*get address*/
897 1.114.6.2 mjf db_dot = (db_addr_t) addr;
898 1.114.6.2 mjf db_last_addr = db_dot;
899 1.114.6.2 mjf have_addr = true;
900 1.114.6.2 mjf } else {
901 1.114.6.2 mjf addr = (db_expr_t) db_dot;
902 1.114.6.2 mjf have_addr = false;
903 1.114.6.2 mjf }
904 1.114.6.2 mjf
905 1.114.6.2 mjf t = db_read_token();
906 1.114.6.2 mjf if (t == tCOMMA) { /*Get count*/
907 1.114.6.2 mjf if (!db_expression(&count)) {
908 1.114.6.2 mjf db_printf("Count missing\n");
909 1.114.6.2 mjf db_flush_lex();
910 1.114.6.2 mjf return;
911 1.114.6.2 mjf }
912 1.114.6.3 mjf } else {
913 1.114.6.2 mjf db_unread_token(t);
914 1.114.6.2 mjf count = -1;
915 1.114.6.2 mjf }
916 1.114.6.2 mjf if ((command->flag & CS_MORE) == 0) {
917 1.114.6.2 mjf db_skip_to_eol();
918 1.114.6.2 mjf }
919 1.114.6.2 mjf }
920 1.114.6.2 mjf }
921 1.114.6.2 mjf
922 1.114.6.2 mjf if (command->flag & CS_NOREPEAT) {
923 1.114.6.2 mjf *last_cmdp = NULL;
924 1.114.6.2 mjf last_count = 0;
925 1.114.6.2 mjf } else {
926 1.114.6.2 mjf *last_cmdp = command;
927 1.114.6.2 mjf last_count = count;
928 1.114.6.2 mjf }
929 1.114.6.2 mjf
930 1.114.6.2 mjf if (command != NULL) {
931 1.114.6.2 mjf /*
932 1.114.6.2 mjf * Execute the command.
933 1.114.6.2 mjf */
934 1.114.6.2 mjf if (command->fcn != NULL)
935 1.114.6.2 mjf (*command->fcn)(addr, have_addr, count, modif);
936 1.114.6.2 mjf
937 1.114.6.2 mjf if (command->flag & CS_SET_DOT) {
938 1.114.6.2 mjf /*
939 1.114.6.2 mjf * If command changes dot, set dot to
940 1.114.6.2 mjf * previous address displayed (if 'ed' style).
941 1.114.6.2 mjf */
942 1.114.6.2 mjf if (db_ed_style)
943 1.114.6.2 mjf db_dot = db_prev;
944 1.114.6.2 mjf else
945 1.114.6.2 mjf db_dot = db_next;
946 1.114.6.2 mjf } else {
947 1.114.6.2 mjf /*
948 1.114.6.2 mjf * If command does not change dot,
949 1.114.6.2 mjf * set 'next' location to be the same.
950 1.114.6.2 mjf */
951 1.114.6.2 mjf db_next = db_dot;
952 1.114.6.2 mjf }
953 1.114.6.2 mjf }
954 1.114.6.2 mjf }
955 1.114.6.2 mjf
956 1.114.6.2 mjf /*
957 1.114.6.2 mjf * Print help for commands
958 1.114.6.2 mjf */
959 1.114.6.2 mjf static void
960 1.114.6.2 mjf db_help_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
961 1.114.6.2 mjf const char *modif)
962 1.114.6.2 mjf {
963 1.114.6.3 mjf
964 1.114.6.2 mjf const struct db_cmd_tbl_en_head *list;
965 1.114.6.2 mjf const struct db_cmd_tbl_en *list_ent;
966 1.114.6.2 mjf const struct db_command *help = NULL;
967 1.114.6.2 mjf int t, result;
968 1.114.6.3 mjf
969 1.114.6.2 mjf t = db_read_token();
970 1.114.6.2 mjf /* is there another command after the "help"? */
971 1.114.6.2 mjf if (t == tIDENT){
972 1.114.6.2 mjf
973 1.114.6.2 mjf switch(db_get_list_type(db_tok_string)) {
974 1.114.6.2 mjf
975 1.114.6.2 mjf case DDB_BASE_CMD:
976 1.114.6.2 mjf list=&db_base_cmd_list;
977 1.114.6.2 mjf break;
978 1.114.6.2 mjf case DDB_SHOW_CMD:
979 1.114.6.2 mjf list=&db_show_cmd_list;
980 1.114.6.2 mjf /* read the show subcommand */
981 1.114.6.3 mjf t = db_read_token();
982 1.114.6.2 mjf
983 1.114.6.2 mjf if (t != tIDENT) {
984 1.114.6.2 mjf /* no subcommand, print the list */
985 1.114.6.2 mjf db_cmd_list(list);
986 1.114.6.2 mjf db_flush_lex();
987 1.114.6.2 mjf return;
988 1.114.6.3 mjf }
989 1.114.6.3 mjf
990 1.114.6.2 mjf break;
991 1.114.6.2 mjf case DDB_MACH_CMD:
992 1.114.6.2 mjf list=&db_mach_cmd_list;
993 1.114.6.2 mjf /* read machine subcommand */
994 1.114.6.3 mjf t = db_read_token();
995 1.114.6.2 mjf
996 1.114.6.2 mjf if (t != tIDENT) {
997 1.114.6.2 mjf /* no subcommand - just print the list */
998 1.114.6.2 mjf db_cmd_list(list);
999 1.114.6.2 mjf db_flush_lex();
1000 1.114.6.2 mjf return;
1001 1.114.6.2 mjf }
1002 1.114.6.2 mjf break;
1003 1.114.6.2 mjf
1004 1.114.6.2 mjf default:
1005 1.114.6.2 mjf db_printf("No such command\n");
1006 1.114.6.2 mjf db_flush_lex();
1007 1.114.6.2 mjf return;
1008 1.114.6.2 mjf }
1009 1.114.6.3 mjf COMPAT_RET:
1010 1.114.6.2 mjf TAILQ_FOREACH(list_ent,list,db_cmd_next){
1011 1.114.6.2 mjf result = db_cmd_search(db_tok_string, list_ent->db_cmd,
1012 1.114.6.2 mjf &help);
1013 1.114.6.2 mjf /* after CMD_UNIQUE only a single command
1014 1.114.6.2 mjf name is possible */
1015 1.114.6.2 mjf if (result == CMD_UNIQUE)
1016 1.114.6.2 mjf break;
1017 1.114.6.2 mjf }
1018 1.114.6.2 mjf #ifdef DDB_VERBOSE_HELP
1019 1.114.6.2 mjf /*print help*/
1020 1.114.6.2 mjf
1021 1.114.6.2 mjf db_printf("Command: %s\n",help->name);
1022 1.114.6.2 mjf
1023 1.114.6.2 mjf if (help->cmd_descr != NULL)
1024 1.114.6.2 mjf db_printf(" Description: %s\n",help->cmd_descr);
1025 1.114.6.3 mjf
1026 1.114.6.2 mjf if (help->cmd_arg != NULL)
1027 1.114.6.2 mjf db_printf(" Arguments: %s\n",help->cmd_arg);
1028 1.114.6.2 mjf
1029 1.114.6.2 mjf if (help->cmd_arg_help != NULL)
1030 1.114.6.2 mjf db_printf(" Arguments description:\n%s\n",
1031 1.114.6.2 mjf help->cmd_arg_help);
1032 1.114.6.2 mjf
1033 1.114.6.2 mjf if ((help->cmd_arg == NULL) && (help->cmd_descr == NULL))
1034 1.114.6.2 mjf db_printf("%s Doesn't have any help message included.\n",
1035 1.114.6.2 mjf help->name);
1036 1.114.6.2 mjf #endif
1037 1.114.6.2 mjf /* check compatibility flag */
1038 1.114.6.2 mjf /*
1039 1.114.6.2 mjf * The "show all" command table has been merged with the
1040 1.114.6.2 mjf * "show" command table - but we want to keep the old UI
1041 1.114.6.2 mjf * available. So if we find a CS_COMPAT entry, we read
1042 1.114.6.2 mjf * the next token and try again.
1043 1.114.6.2 mjf */
1044 1.114.6.2 mjf if (help->flag == CS_COMPAT){
1045 1.114.6.2 mjf t = db_read_token();
1046 1.114.6.2 mjf
1047 1.114.6.2 mjf if (t != tIDENT){
1048 1.114.6.2 mjf db_cmd_list(list);
1049 1.114.6.2 mjf db_flush_lex();
1050 1.114.6.2 mjf return;
1051 1.114.6.2 mjf }
1052 1.114.6.2 mjf
1053 1.114.6.2 mjf goto COMPAT_RET;
1054 1.114.6.2 mjf /* support only level 2 commands here */
1055 1.114.6.2 mjf } else {
1056 1.114.6.2 mjf db_skip_to_eol();
1057 1.114.6.2 mjf }
1058 1.114.6.3 mjf
1059 1.114.6.2 mjf } else /* t != tIDENT */
1060 1.114.6.2 mjf /* print base commands */
1061 1.114.6.2 mjf db_cmd_list(&db_base_cmd_list);
1062 1.114.6.3 mjf
1063 1.114.6.2 mjf return;
1064 1.114.6.2 mjf }
1065 1.114.6.2 mjf
1066 1.114.6.2 mjf /*ARGSUSED*/
1067 1.114.6.2 mjf static void
1068 1.114.6.2 mjf db_map_print_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
1069 1.114.6.2 mjf const char *modif)
1070 1.114.6.2 mjf {
1071 1.114.6.2 mjf bool full = false;
1072 1.114.6.2 mjf
1073 1.114.6.2 mjf if (modif[0] == 'f')
1074 1.114.6.2 mjf full = true;
1075 1.114.6.2 mjf
1076 1.114.6.2 mjf if (have_addr == false)
1077 1.114.6.4 mjf addr = (db_expr_t)(uintptr_t) kernel_map;
1078 1.114.6.2 mjf
1079 1.114.6.4 mjf uvm_map_printit((struct vm_map *)(uintptr_t) addr, full, db_printf);
1080 1.114.6.2 mjf }
1081 1.114.6.2 mjf
1082 1.114.6.2 mjf /*ARGSUSED*/
1083 1.114.6.2 mjf static void
1084 1.114.6.2 mjf db_malloc_print_cmd(db_expr_t addr, bool have_addr,
1085 1.114.6.2 mjf db_expr_t count, const char *modif)
1086 1.114.6.2 mjf {
1087 1.114.6.2 mjf
1088 1.114.6.2 mjf #ifdef MALLOC_DEBUG
1089 1.114.6.2 mjf if (!have_addr)
1090 1.114.6.2 mjf addr = 0;
1091 1.114.6.2 mjf
1092 1.114.6.2 mjf debug_malloc_printit(db_printf, (vaddr_t) addr);
1093 1.114.6.2 mjf #else
1094 1.114.6.2 mjf db_printf("The kernel is not built with the MALLOC_DEBUG option.\n");
1095 1.114.6.2 mjf #endif /* MALLOC_DEBUG */
1096 1.114.6.2 mjf }
1097 1.114.6.2 mjf
1098 1.114.6.2 mjf /*ARGSUSED*/
1099 1.114.6.2 mjf static void
1100 1.114.6.2 mjf db_object_print_cmd(db_expr_t addr, bool have_addr,
1101 1.114.6.2 mjf db_expr_t count, const char *modif)
1102 1.114.6.2 mjf {
1103 1.114.6.2 mjf bool full = false;
1104 1.114.6.2 mjf
1105 1.114.6.2 mjf if (modif[0] == 'f')
1106 1.114.6.2 mjf full = true;
1107 1.114.6.2 mjf
1108 1.114.6.4 mjf uvm_object_printit((struct uvm_object *)(uintptr_t) addr, full,
1109 1.114.6.2 mjf db_printf);
1110 1.114.6.2 mjf }
1111 1.114.6.2 mjf
1112 1.114.6.2 mjf /*ARGSUSED*/
1113 1.114.6.2 mjf static void
1114 1.114.6.2 mjf db_page_print_cmd(db_expr_t addr, bool have_addr,
1115 1.114.6.2 mjf db_expr_t count, const char *modif)
1116 1.114.6.2 mjf {
1117 1.114.6.2 mjf bool full = false;
1118 1.114.6.2 mjf
1119 1.114.6.2 mjf if (modif[0] == 'f')
1120 1.114.6.2 mjf full = true;
1121 1.114.6.2 mjf
1122 1.114.6.4 mjf uvm_page_printit((struct vm_page *)(uintptr_t) addr, full, db_printf);
1123 1.114.6.2 mjf }
1124 1.114.6.2 mjf
1125 1.114.6.2 mjf /*ARGSUSED*/
1126 1.114.6.2 mjf static void
1127 1.114.6.2 mjf db_show_all_pages(db_expr_t addr, bool have_addr,
1128 1.114.6.2 mjf db_expr_t count, const char *modif)
1129 1.114.6.2 mjf {
1130 1.114.6.2 mjf
1131 1.114.6.2 mjf uvm_page_printall(db_printf);
1132 1.114.6.2 mjf }
1133 1.114.6.2 mjf
1134 1.114.6.2 mjf /*ARGSUSED*/
1135 1.114.6.2 mjf static void
1136 1.114.6.2 mjf db_buf_print_cmd(db_expr_t addr, bool have_addr,
1137 1.114.6.2 mjf db_expr_t count, const char *modif)
1138 1.114.6.2 mjf {
1139 1.114.6.2 mjf bool full = false;
1140 1.114.6.2 mjf
1141 1.114.6.2 mjf if (modif[0] == 'f')
1142 1.114.6.2 mjf full = true;
1143 1.114.6.2 mjf
1144 1.114.6.4 mjf vfs_buf_print((struct buf *)(uintptr_t) addr, full, db_printf);
1145 1.114.6.2 mjf }
1146 1.114.6.2 mjf
1147 1.114.6.2 mjf /*ARGSUSED*/
1148 1.114.6.2 mjf static void
1149 1.114.6.2 mjf db_event_print_cmd(db_expr_t addr, bool have_addr,
1150 1.114.6.2 mjf db_expr_t count, const char *modif)
1151 1.114.6.2 mjf {
1152 1.114.6.2 mjf bool full = false;
1153 1.114.6.2 mjf
1154 1.114.6.2 mjf if (modif[0] == 'f')
1155 1.114.6.2 mjf full = true;
1156 1.114.6.2 mjf
1157 1.114.6.2 mjf event_print(full, db_printf);
1158 1.114.6.2 mjf }
1159 1.114.6.2 mjf
1160 1.114.6.2 mjf /*ARGSUSED*/
1161 1.114.6.2 mjf static void
1162 1.114.6.2 mjf db_vnode_print_cmd(db_expr_t addr, bool have_addr,
1163 1.114.6.2 mjf db_expr_t count, const char *modif)
1164 1.114.6.2 mjf {
1165 1.114.6.2 mjf bool full = false;
1166 1.114.6.2 mjf
1167 1.114.6.2 mjf if (modif[0] == 'f')
1168 1.114.6.2 mjf full = true;
1169 1.114.6.2 mjf
1170 1.114.6.4 mjf vfs_vnode_print((struct vnode *)(uintptr_t) addr, full, db_printf);
1171 1.114.6.2 mjf }
1172 1.114.6.2 mjf
1173 1.114.6.2 mjf static void
1174 1.114.6.2 mjf db_mount_print_cmd(db_expr_t addr, bool have_addr,
1175 1.114.6.2 mjf db_expr_t count, const char *modif)
1176 1.114.6.2 mjf {
1177 1.114.6.2 mjf bool full = false;
1178 1.114.6.2 mjf
1179 1.114.6.2 mjf if (modif[0] == 'f')
1180 1.114.6.2 mjf full = true;
1181 1.114.6.2 mjf
1182 1.114.6.4 mjf vfs_mount_print((struct mount *)(uintptr_t) addr, full, db_printf);
1183 1.114.6.2 mjf }
1184 1.114.6.2 mjf
1185 1.114.6.2 mjf /*ARGSUSED*/
1186 1.114.6.2 mjf static void
1187 1.114.6.2 mjf db_mbuf_print_cmd(db_expr_t addr, bool have_addr,
1188 1.114.6.2 mjf db_expr_t count, const char *modif)
1189 1.114.6.2 mjf {
1190 1.114.6.2 mjf
1191 1.114.6.4 mjf m_print((const struct mbuf *)(uintptr_t) addr, modif, db_printf);
1192 1.114.6.2 mjf }
1193 1.114.6.2 mjf
1194 1.114.6.2 mjf /*ARGSUSED*/
1195 1.114.6.2 mjf static void
1196 1.114.6.2 mjf db_pool_print_cmd(db_expr_t addr, bool have_addr,
1197 1.114.6.2 mjf db_expr_t count, const char *modif)
1198 1.114.6.2 mjf {
1199 1.114.6.2 mjf
1200 1.114.6.4 mjf pool_printit((struct pool *)(uintptr_t) addr, modif, db_printf);
1201 1.114.6.2 mjf }
1202 1.114.6.2 mjf
1203 1.114.6.2 mjf /*ARGSUSED*/
1204 1.114.6.2 mjf static void
1205 1.114.6.2 mjf db_namecache_print_cmd(db_expr_t addr, bool have_addr,
1206 1.114.6.2 mjf db_expr_t count, const char *modif)
1207 1.114.6.2 mjf {
1208 1.114.6.2 mjf
1209 1.114.6.4 mjf namecache_print((struct vnode *)(uintptr_t) addr, db_printf);
1210 1.114.6.2 mjf }
1211 1.114.6.2 mjf
1212 1.114.6.2 mjf /*ARGSUSED*/
1213 1.114.6.2 mjf static void
1214 1.114.6.2 mjf db_uvmexp_print_cmd(db_expr_t addr, bool have_addr,
1215 1.114.6.2 mjf db_expr_t count, const char *modif)
1216 1.114.6.2 mjf {
1217 1.114.6.2 mjf
1218 1.114.6.2 mjf uvmexp_print(db_printf);
1219 1.114.6.2 mjf }
1220 1.114.6.2 mjf
1221 1.114.6.3 mjf #ifdef UVMHIST
1222 1.114.6.3 mjf /*ARGSUSED*/
1223 1.114.6.3 mjf static void
1224 1.114.6.3 mjf db_uvmhist_print_cmd(db_expr_t addr, bool have_addr,
1225 1.114.6.3 mjf db_expr_t count, const char *modif)
1226 1.114.6.3 mjf {
1227 1.114.6.3 mjf
1228 1.114.6.3 mjf uvmhist_print(db_printf);
1229 1.114.6.3 mjf }
1230 1.114.6.3 mjf #endif
1231 1.114.6.3 mjf
1232 1.114.6.2 mjf /*ARGSUSED*/
1233 1.114.6.2 mjf static void
1234 1.114.6.2 mjf db_lock_print_cmd(db_expr_t addr, bool have_addr,
1235 1.114.6.2 mjf db_expr_t count, const char *modif)
1236 1.114.6.2 mjf {
1237 1.114.6.2 mjf
1238 1.114.6.2 mjf lockdebug_lock_print((void *)addr, db_printf);
1239 1.114.6.2 mjf }
1240 1.114.6.2 mjf
1241 1.114.6.2 mjf /*
1242 1.114.6.2 mjf * Call random function:
1243 1.114.6.2 mjf * !expr(arg,arg,arg)
1244 1.114.6.2 mjf */
1245 1.114.6.2 mjf /*ARGSUSED*/
1246 1.114.6.2 mjf static void
1247 1.114.6.2 mjf db_fncall(db_expr_t addr, bool have_addr,
1248 1.114.6.2 mjf db_expr_t count, const char *modif)
1249 1.114.6.2 mjf {
1250 1.114.6.2 mjf db_expr_t fn_addr;
1251 1.114.6.2 mjf #define MAXARGS 11
1252 1.114.6.2 mjf db_expr_t args[MAXARGS];
1253 1.114.6.2 mjf int nargs = 0;
1254 1.114.6.2 mjf db_expr_t retval;
1255 1.114.6.2 mjf db_expr_t (*func)(db_expr_t, ...);
1256 1.114.6.2 mjf int t;
1257 1.114.6.2 mjf
1258 1.114.6.2 mjf if (!db_expression(&fn_addr)) {
1259 1.114.6.2 mjf db_printf("Bad function\n");
1260 1.114.6.2 mjf db_flush_lex();
1261 1.114.6.2 mjf return;
1262 1.114.6.2 mjf }
1263 1.114.6.4 mjf func = (db_expr_t (*)(db_expr_t, ...))(uintptr_t) fn_addr;
1264 1.114.6.2 mjf
1265 1.114.6.2 mjf t = db_read_token();
1266 1.114.6.2 mjf if (t == tLPAREN) {
1267 1.114.6.2 mjf if (db_expression(&args[0])) {
1268 1.114.6.2 mjf nargs++;
1269 1.114.6.2 mjf while ((t = db_read_token()) == tCOMMA) {
1270 1.114.6.2 mjf if (nargs == MAXARGS) {
1271 1.114.6.2 mjf db_printf("Too many arguments\n");
1272 1.114.6.2 mjf db_flush_lex();
1273 1.114.6.2 mjf return;
1274 1.114.6.2 mjf }
1275 1.114.6.2 mjf if (!db_expression(&args[nargs])) {
1276 1.114.6.2 mjf db_printf("Argument missing\n");
1277 1.114.6.2 mjf db_flush_lex();
1278 1.114.6.2 mjf return;
1279 1.114.6.2 mjf }
1280 1.114.6.2 mjf nargs++;
1281 1.114.6.2 mjf }
1282 1.114.6.2 mjf db_unread_token(t);
1283 1.114.6.2 mjf }
1284 1.114.6.2 mjf if (db_read_token() != tRPAREN) {
1285 1.114.6.2 mjf db_printf("?\n");
1286 1.114.6.2 mjf db_flush_lex();
1287 1.114.6.2 mjf return;
1288 1.114.6.2 mjf }
1289 1.114.6.2 mjf }
1290 1.114.6.2 mjf db_skip_to_eol();
1291 1.114.6.2 mjf
1292 1.114.6.2 mjf while (nargs < MAXARGS) {
1293 1.114.6.2 mjf args[nargs++] = 0;
1294 1.114.6.2 mjf }
1295 1.114.6.2 mjf
1296 1.114.6.2 mjf retval = (*func)(args[0], args[1], args[2], args[3], args[4],
1297 1.114.6.2 mjf args[5], args[6], args[7], args[8], args[9]);
1298 1.114.6.2 mjf db_printf("%s\n", db_num_to_str(retval));
1299 1.114.6.2 mjf }
1300 1.114.6.2 mjf
1301 1.114.6.2 mjf static void
1302 1.114.6.2 mjf db_reboot_cmd(db_expr_t addr, bool have_addr,
1303 1.114.6.2 mjf db_expr_t count, const char *modif)
1304 1.114.6.2 mjf {
1305 1.114.6.2 mjf db_expr_t bootflags;
1306 1.114.6.2 mjf
1307 1.114.6.2 mjf /* Flags, default to RB_AUTOBOOT */
1308 1.114.6.2 mjf if (!db_expression(&bootflags))
1309 1.114.6.2 mjf bootflags = (db_expr_t)RB_AUTOBOOT;
1310 1.114.6.2 mjf if (db_read_token() != tEOL) {
1311 1.114.6.2 mjf db_error("?\n");
1312 1.114.6.2 mjf /*NOTREACHED*/
1313 1.114.6.2 mjf }
1314 1.114.6.2 mjf /*
1315 1.114.6.2 mjf * We are leaving DDB, never to return upward.
1316 1.114.6.2 mjf * Clear db_recover so that we can debug faults in functions
1317 1.114.6.2 mjf * called from cpu_reboot.
1318 1.114.6.2 mjf */
1319 1.114.6.2 mjf db_recover = 0;
1320 1.114.6.2 mjf cpu_reboot((int)bootflags, NULL);
1321 1.114.6.2 mjf }
1322 1.114.6.2 mjf
1323 1.114.6.2 mjf static void
1324 1.114.6.2 mjf db_sifting_cmd(db_expr_t addr, bool have_addr,
1325 1.114.6.2 mjf db_expr_t count, const char *modif)
1326 1.114.6.2 mjf {
1327 1.114.6.2 mjf int mode, t;
1328 1.114.6.2 mjf
1329 1.114.6.2 mjf t = db_read_token();
1330 1.114.6.2 mjf if (t == tSLASH) {
1331 1.114.6.2 mjf t = db_read_token();
1332 1.114.6.2 mjf if (t != tIDENT) {
1333 1.114.6.2 mjf bad_modifier:
1334 1.114.6.2 mjf db_printf("Bad modifier\n");
1335 1.114.6.2 mjf db_flush_lex();
1336 1.114.6.2 mjf return;
1337 1.114.6.2 mjf }
1338 1.114.6.2 mjf if (!strcmp(db_tok_string, "F"))
1339 1.114.6.2 mjf mode = 'F';
1340 1.114.6.2 mjf else
1341 1.114.6.2 mjf goto bad_modifier;
1342 1.114.6.2 mjf t = db_read_token();
1343 1.114.6.2 mjf } else
1344 1.114.6.2 mjf mode = 0;
1345 1.114.6.2 mjf
1346 1.114.6.2 mjf if (t == tIDENT)
1347 1.114.6.2 mjf db_sifting(db_tok_string, mode);
1348 1.114.6.2 mjf else {
1349 1.114.6.2 mjf db_printf("Bad argument (non-string)\n");
1350 1.114.6.2 mjf db_flush_lex();
1351 1.114.6.2 mjf }
1352 1.114.6.2 mjf }
1353 1.114.6.2 mjf
1354 1.114.6.2 mjf static void
1355 1.114.6.2 mjf db_stack_trace_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1356 1.114.6.2 mjf {
1357 1.114.6.2 mjf register const char *cp = modif;
1358 1.114.6.2 mjf register char c;
1359 1.114.6.2 mjf void (*pr)(const char *, ...);
1360 1.114.6.2 mjf
1361 1.114.6.2 mjf pr = db_printf;
1362 1.114.6.2 mjf while ((c = *cp++) != 0)
1363 1.114.6.2 mjf if (c == 'l')
1364 1.114.6.2 mjf pr = printf;
1365 1.114.6.2 mjf
1366 1.114.6.2 mjf if (count == -1)
1367 1.114.6.2 mjf count = 65535;
1368 1.114.6.2 mjf
1369 1.114.6.2 mjf db_stack_trace_print(addr, have_addr, count, modif, pr);
1370 1.114.6.2 mjf }
1371 1.114.6.2 mjf
1372 1.114.6.2 mjf static void
1373 1.114.6.2 mjf db_sync_cmd(db_expr_t addr, bool have_addr,
1374 1.114.6.2 mjf db_expr_t count, const char *modif)
1375 1.114.6.2 mjf {
1376 1.114.6.2 mjf
1377 1.114.6.2 mjf /*
1378 1.114.6.2 mjf * We are leaving DDB, never to return upward.
1379 1.114.6.2 mjf * Clear db_recover so that we can debug faults in functions
1380 1.114.6.2 mjf * called from cpu_reboot.
1381 1.114.6.2 mjf */
1382 1.114.6.2 mjf db_recover = 0;
1383 1.114.6.2 mjf panicstr = "dump forced via kernel debugger";
1384 1.114.6.2 mjf cpu_reboot(RB_DUMP, NULL);
1385 1.114.6.2 mjf }
1386 1.114.6.2 mjf
1387 1.114.6.2 mjf /*
1388 1.114.6.2 mjf * Describe what an address is
1389 1.114.6.2 mjf */
1390 1.114.6.2 mjf void
1391 1.114.6.2 mjf db_whatis_cmd(db_expr_t address, bool have_addr,
1392 1.114.6.2 mjf db_expr_t count, const char *modif)
1393 1.114.6.2 mjf {
1394 1.114.6.2 mjf const uintptr_t addr = (uintptr_t)address;
1395 1.114.6.2 mjf
1396 1.114.6.2 mjf lwp_whatis(addr, db_printf);
1397 1.114.6.2 mjf pool_whatis(addr, db_printf);
1398 1.114.6.2 mjf vmem_whatis(addr, db_printf);
1399 1.114.6.2 mjf uvm_whatis(addr, db_printf);
1400 1.114.6.2 mjf }
1401